首页 > 解决方案 > 如何从画布上的多个旋转弧中删除直线?

问题描述

我想在画布上创建星轨

创建它的想法是,我必须绘制多个增加大小的图像,并计算下一个图像位置。将多个图像存储在数组中。每次绘制随机选择图像,并以不同的角度绘制每个图像。

我做到了。

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>

有什么办法可以去掉那条直线吗?

标签: javascripthtmlcanvas

解决方案


不知道你为什么要打电话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, ...);

推荐阅读