javascript - 如何从画布上的多个旋转弧中删除直线?
问题描述
我想在画布上创建星轨。
创建它的想法是,我必须绘制多个增加大小的图像,并计算下一个图像位置。将多个图像存储在数组中。每次绘制随机选择图像,并以不同的角度绘制每个图像。
我做到了。
var canvas=document.getElementById('canvas'),ctx=canvas.getContext('2d');
var starsimage=['https://1.bp.blogspot.com/-prwJzDDwQRU/XTjNfQhQnDI/AAAAAAAACBo/wpbhqkfc-9wQQeg95O6poFbFyu77q4vdACLcBGAs/s1600/CircleWhite100.png','https://1.bp.blogspot.com/-lm4F2UOMCdE/XTjNghXjrOI/AAAAAAAACB0/L6pya6HQk0cU5R5RP9Wo_-Bm_UhO_qCawCLcBGAs/s1600/CircleWhite75.png','https://1.bp.blogspot.com/-7ennrlohEo0/XTjNfoji8KI/AAAAAAAACBw/G0SQhFEZ0IMMf2z3g_Mvbon97BMktSw-QCLcBGAs/s1600/CircleWhite50.png','https://1.bp.blogspot.com/-I7aeA-F4OWY/XTjNfiO-rxI/AAAAAAAACBs/lKYC-SmaWSQWc0PoPVdgCHeyDUPdoJd7gCLcBGAs/s1600/CircleWhite25.png','https://1.bp.blogspot.com/-V2Ak6YU2XNA/XTjNh7iIwZI/AAAAAAAACCA/tNo5Ho6iC4gndoftPJfSCInGqgyfcd6nQCLcBGAs/s1600/TrailBlue100.png','https://1.bp.blogspot.com/-ylpi3AZvces/XTjNi7uy1kI/AAAAAAAACCM/uWZ7_zYRXXQN4q3QRSngCFeT5RoEeG4xgCLcBGAs/s1600/TrailBlue75.png','https://1.bp.blogspot.com/-NoPiS9k0o0U/XTjNivmKVjI/AAAAAAAACCI/gZzDMn9zomMWrQc2hhKfNB9JK0ruh2wyQCLcBGAs/s1600/TrailBlue50.png','https://1.bp.blogspot.com/-KYkWDwtmS7A/XTjNiSE8Y_I/AAAAAAAACCE/jDyTIbJqBBs3FP1tyGFICjShyx_GCCy0gCLcBGAs/s1600/TrailBlue25.png'];
var stars=new Array();var starsloaded=0;
var xpos=0,ypos=0,w=25,h=25,ix=0,xa=25,ya=25,rot=0,ang=0;
for(var i=0;i<starsimage.length;i++){//load images
stars[i]=new Image();stars[i].src=starsimage[i];
stars[i].onload=function(){starsloaded++;if(starsloaded==starsimage.length){
draw();
}}
}
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw(){
xpos=canvas.width/2;ypos=canvas.height/2;
for(var i=0;i<500;i++){//500 images
xy=minmaxdraw(2,4);//gap randomly
ix=randomindeximage(starsimage.length);
w+=xy;h+=xy;ang=minmaxdraw(0,359);
if(i>0){xa=w-xa;ya=h-ya;xpos=xpos-xa/2;ypos=ypos-ya/2;
ctx.save();
ctx.translate(xpos+w/2,ypos+h/2);
rot=ang*Math.PI/180;ctx.rotate(rot);
ctx.drawImage(stars[ix],-w/2,-h/2,w,h);
ctx.restore();
xa=w;ya=h;
}
else{ctx.drawImage(stars[ix],xpos,ypos,w,h)}
}
}
body{margin:0;padding:0;position:relative;background:#101010;height:580px;width:100%}
#canvas{z-index:2;background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;transform:translate(-50%,-50%)}
body:before{content:'';z-index:1;position:absolute;width:100%;height:100%;left:0;top:0;background:linear-gradient(15deg, #1458ac, #000);}
<canvas id="canvas" width="640" height="580"></canvas>
但。质量很差。因为图像大小是静态的,如果增量宽度大于实际图像大小,则模糊,并且小星星几乎不可见
我认为,最好用多个弧来创建它。这个想法是一样的,我必须画多条弧线。但是,我是假人,我用两幅画布制作,每幅画布的角度不同。(这实际上与我之前的工作相同,但当时,我使用了 1 个已切割圆圈的图像)。因为如果我只在一张画布上制作它,就会出现直线。所以,我在每个画布上画了多条弧线。它有效,并且没有出现直线。(还是基本弧线)
var canvas1=document.getElementById('canvas1'),ctx=canvas1.getContext('2d'),canvas2=document.getElementById('canvas2'),ctx2=canvas2.getContext('2d');var xy=0;var angle=new Array();
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw1(){
var xpos=canvas1.width/2;var ypos=canvas1.height/2;var r=15,ang=0;
ctx.beginPath();
for(var i=0;i<55;i++){
r+=minmaxdraw(4,9);
ctx.moveTo(xpos + r, ypos);
ctx.arc(xpos, ypos, r, 0, 1.5*Math.PI,true);
}ctx.stroke();
}
function draw2(){
var xpos=canvas2.width/2;var ypos=canvas2.height/2;var r=15;
ctx2.beginPath();
for(var t=0;t<55;t++){
r+=minmaxdraw(4,9);
ctx2.moveTo(xpos, ypos + r);
ctx2.arc(xpos, ypos, r, Math.PI / 2, Math.PI);
}ctx2.stroke();
}
draw1();draw2();
body{margin:0;padding:0;position:relative;height:480px;width:100%}
.canvas{background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;margin:-50% 0 0 -50%}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
它还没有旋转。所以,如果我想制作圆形轨迹,我必须像以前对图像所做的那样随机旋转每个弧线,但问题就在这里。直线来得很邪恶。
var canvas1=document.getElementById('canvas1'),ctx=canvas1.getContext('2d'),canvas2=document.getElementById('canvas2'),ctx2=canvas2.getContext('2d');var xy=0;var angle=new Array();
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw1(){
var xpos=canvas1.width/2;var ypos=canvas1.height/2;
var r=15,ang=0,dx=0,dy=0;
ctx.beginPath();
for(var i=0;i<55;i++){//200 images
ang=minmaxdraw(0,359);
dx=minmaxdraw(0,canvas1.width),dy=minmaxdraw(0,canvas1.height);
r+=minmaxdraw(3,7);
ang=Math.atan2(dx-xpos,dy-ypos);angle[i]=ang;
ctx.moveTo(xpos, ypos);
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5,true);
}ctx.stroke();
}
function draw2(){
var xpos=canvas2.width/2;var ypos=canvas2.height/2;var r=15;
ctx2.beginPath();
for(var t=0;t<55;t++){
r+=minmaxdraw(3,7);
ctx2.moveTo(xpos, ypos + r);
ctx2.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
}ctx2.stroke();
}
draw1();draw2();
body{margin:0;padding:0;position:relative;height:480px;width:100%}
.canvas{background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;margin:-50% 0 0 -50%}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
有什么办法可以去掉那条直线吗?
解决方案
不知道你为什么要打电话moveTo
,也许我只是不明白这个问题,但我只是在循环中beginPath
移动。stroke
var canvas1 = document.getElementById('canvas1'),
ctx = canvas1.getContext('2d'),
canvas2 = document.getElementById('canvas2'),
ctx2 = canvas2.getContext('2d');
var xy = 0;
var angle = new Array();
function minmaxdraw(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function randomindeximage(l) {
return Math.floor(Math.random() * l)
}
function draw1() {
var xpos = canvas1.width / 2;
var ypos = canvas1.height / 2;
var r = 15,
ang = 0,
dx = 0,
dy = 0;
for (var i = 0; i < 55; i++) { //200 images
ang = minmaxdraw(0, 359);
dx = minmaxdraw(0, canvas1.width), dy = minmaxdraw(0, canvas1.height);
r += minmaxdraw(3, 7);
ang = Math.atan2(dx - xpos, dy - ypos);
angle[i] = ang;
ctx.beginPath();
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5, true);
ctx.stroke();
}
}
function draw2() {
var xpos = canvas2.width / 2;
var ypos = canvas2.height / 2;
var r = 15;
for (var t = 0; t < 55; t++) {
r += minmaxdraw(3, 7);
ctx2.beginPath();
ctx2.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
ctx2.stroke();
}
}
draw1();
draw2();
body {
margin: 0;
padding: 0;
position: relative;
height: 550px;
width: 100%
}
.canvas {
background-color: transparent;
position: absolute;
width: 100vw;
left: 50%;
top: 50%;
margin: -50% 0 0 -50%
}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
另外我不明白你为什么有 2 个画布。只需一个就可以正常工作
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
var xy = 0;
var angle = new Array();
function minmaxdraw(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function randomindeximage(l) {
return Math.floor(Math.random() * l)
}
function draw1() {
var xpos = canvas.width / 2;
var ypos = canvas.height / 2;
var r = 15,
ang = 0,
dx = 0,
dy = 0;
for (var i = 0; i < 55; i++) { //200 images
ang = minmaxdraw(0, 359);
dx = minmaxdraw(0, canvas.width), dy = minmaxdraw(0, canvas.height);
r += minmaxdraw(3, 7);
ang = Math.atan2(dx - xpos, dy - ypos);
angle[i] = ang;
ctx.beginPath();
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5, true);
ctx.stroke();
}
}
function draw2() {
var xpos = canvas.width / 2;
var ypos = canvas.height / 2;
var r = 15;
for (var t = 0; t < 55; t++) {
r += minmaxdraw(3, 7);
ctx.beginPath();
ctx.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
ctx.stroke();
}
}
draw1();
draw2();
<canvas id='canvas' class='canvas' width='640' height='480'></canvas>
你之前有线条的原因arc
是加分。
arc
实际上是这个
// pseudo code
function arc(x, y, radius, start, end) {
const numSegments = 100; // no idea what number real arc uses here
for (let i = 0; i < numSegments; ++i) {
const angle = start + (end - start) * i / numSegments;
ctx.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
}
}
如您所见,上面的代码只是在圆弧周围添加点。所以如果你做一个
ctx.moveTo(x, y);
ctx.arc(x, y, ...);
您在弧的中心添加一个点,然后在边缘添加更多点。这就是为什么你要从每个弧的中心到边缘得到一条线。
如果您想保留与您的代码相同的代码并且一次划过所有弧线,那么您需要更改moveTo
以移动到弧线的边缘而不是中心。
ctx.moveTo(x + Math.cos(start) * radius, y + Math.sin(start) * radius);
ctx.arc(x, y, radius, start, ...);
推荐阅读
- ios - iOS 测试:iOS Sandbox 设置中没有出现“Reset Eligibility”
- java - 三元如果包含函数结果
- python - 如何从 AWS S3 嵌套目录中读取泡菜文件?
- vba - 两张表过滤数据结果仅选择性列复制粘贴到另一张表数据粘贴时不应替换
- mysql - 如何查询具有单引号的 json 数据类型列
- mongodb - 有没有更快的方法来克隆有限的 mongo 数据库
- ios - 在 tableView didSelectRowAt indexPath iOS 之前准备 segue 调用
- html - a href 不适用于带有 :after content:''" 的图像;
- c# - 当 SetParent() 不起作用时如何在面板中运行外部应用程序 C#
- visual-studio-code - VS Code Elixir F2“重命名符号”不起作用