如何从画布上的多个旋转弧线上删除直线?

时间:2019-07-24 23:19:18

标签: javascript html canvas

我想在画布上创建Star Trail

创建它的想法是,我必须绘制多个尺寸递增的图像,并对下一个图像位置进行一些计算。将多个图像存储在数组中。每次绘制时随机选择图像,然后以不同角度绘制图像。

我做到了。

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>

有什么办法可以消除那条直线?

1 个答案:

答案 0 :(得分:1)

不知道为什么要打给moveTo的电话,也许我只是不明白这个问题,但我只是将beginPathstroke移入了循环。

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, ...);