下面的代码几乎可以用,但是我想通过使用单个makeline()函数使其简短而简单,以避免重复代码行。 我希望加载图像保持不变,只是我希望代码简短。通过使用上述功能。正如您在下面看到的,代码太长,运行时,行调整不正确。 我希望形状保持不变,线条的位置应该只是一点点调整
<!DOCTYPE html>
<html>
<head>
<style>
myCanvas {
border: 1px;
background: rgba( 240, 238, 238, 0.898);
}
</style>
</head>
<body>
<canvas id="canvas" width="1000" height="1000" style="border: ">
</canvas>
<script>
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.translate(470, 470)
ctx.rotate(15 * Math.PI / 180);
ctx.moveTo(25, 45);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(55 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(45 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(45 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(50 * Math.PI / 180);
ctx.moveTo(25, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(50 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(40 * Math.PI / 180);
ctx.moveTo(35, 50);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(5 * Math.PI / 180);
ctx.moveTo(35, 50);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(15 * Math.PI / 180);
ctx.moveTo(35, 45);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(15 * Math.PI / 180);
ctx.moveTo(35, 45);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(25 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
ctx.beginPath();
ctx.rotate(45 * Math.PI / 180);
ctx.moveTo(35, 35);
ctx.lineTo(100, 150);
ctx.stroke();
</script>
</body>
</html>
答案 0 :(得分:1)
好像您想画出一些阳光,并发出光线。
这是一种比您的代码少得多的选项,关键是使用函数来绘制图形
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var hw = c.width/2;
var hh = c.height/2
ctx.translate(hw, hh)
ctx.lineWidth = 5;
function drawLine(x, y) {
ctx.beginPath();
ctx.moveTo(x * hw/3, y * hh/3);
ctx.lineTo(x * hw, y * hh);
ctx.stroke();
}
var p200 = Math.PI * 200
for (i = 0; i < p200; i += p200 / 12)
drawLine(Math.sin(i/100), Math.cos(i/100));
<canvas id="canvas" width="170" height="170">
使用相同的功能和一些数学技巧,您可以绘制一些更复杂的形状,例如像这样的贝壳:
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
const p200 = Math.PI * 200
function drawLine(x, y, m) {
ctx.beginPath();
ctx.moveTo(x * m/3, y * m/3);
ctx.lineTo(x * m, y * m);
ctx.stroke();
}
function shell(ini, end, mid) {
ctx.lineWidth = 5;
ctx.strokeStyle="black";
for (i = ini; i < end; i += p200 / 124)
drawLine(Math.cos(i/100), Math.sin(i/100), mid - i/10);
ctx.translate(-3, -3)
ctx.strokeStyle="cyan";
for (i = ini; i < end; i += p200 / 96)
drawLine(Math.cos(i/100), Math.sin(i/100), mid - i/10);
ctx.strokeStyle="blue";
for (i = ini; i < end; i += p200 / 48)
drawLine(Math.cos(i/100), Math.sin(i/100), mid - i/10);
ctx.lineWidth = 0.5;
ctx.strokeStyle="green";
for (i = ini; i < end; i += p200 / 48)
drawLine(Math.cos(i/100), Math.sin(i/100), mid - i/10);
}
ctx.translate(70, 60)
shell(0, p200, 95)
ctx.translate(200, 40)
shell(p200/1.8, p200+p200/1.8, 135)
<canvas id="canvas" width="340" height="170">
答案 1 :(得分:1)
如果您想沿直线(与方向成90度角)移动直线并在旋转时旋转它,则以下内容将说明如何使用绝对定位(无ctx.rotate
调用)来做到这一点
一些实用程序功能开始。
// A Point also defines a vector.
const Point = (x,y) => ({x,y});
const Line = (p1, p2) => ({p1, p2});
const lengthOfVec = vec => (vec.x ** 2 + vec.y ** 2) ** 0.5;
const normalVec = line => { // normalize the line and return a vector
const vec = Point(line.p2.x - line.p1.x, line.p2.y - line.p1.y);
const length =lengthOfVec(vec);
vec.x /= length;
vec.y /= length;
return vec;
}
const rotateVec90 = vec => ([vec.y, vec.x] = [vec.x, - vec.y], vec);
我们可以从由端点p1
和p2
定义的直线开始,该直线的法线是一个矢量,该向量在该直线的左侧90度。
我们将创建一个沿该法线移动线的函数,该函数还将使线沿其旋转方向,根据示例的外观,线也需要更改长度,因此我们可以将scale参数添加为好吧。
该函数将为sweepLine(line, distance, rotate, scale)
,其中rotate
以弧度为单位(我将不使用度数),distance
以像素为单位,scale > 1
将增加该行,{ {1}}将缩小行。
scale < 1
我们需要线的中心以及经归一化和法线化的线作为向量
function sweepLine(line, dist, rot, scale){
我们需要中心的新位置,如果要旋转,则新中心将位于圆弧的末端,如果不旋转,则将新位置置于直线的末端。只需沿法线移动中心
const center = Point((line.p1.x + line.p2.x) / 2, (line.p1.y + line.p2.y) / 2);
const lineNorm = normalVec(line);
const norm = rotateVec90(Point(lineNorm.x, lineNorm.y));
现在我们可以缩放线条
if(rot !== 0){
// need the dist of point from center
const ax = line.p2.x - center.x;
const ay = line.p2.y - center.y;
// move the point
center.x += norm.x * dist;
center.y += norm.y * dist;
对于旋转的线,我们需要找到圆弧上的点,并定义圆弧,我们需要该圆弧的中心。圆弧的长度是角度的变化乘以半径,我们没有半径
line.p1.x = center.x - ax * scale
line.p1.y = center.y - ay * scale;
line.p2.x = center.x + ax * scale;
line.p2.y = center.y + ay * scale;
}
圆弧中心与中心的距离为 else {
const arcRadius = dist / rot;
(请注意,arcRadius
可以为负值,这会将中心移至正确的位置)
rot
现在我们有了中心,我们需要圆弧的起始角度,即线的方向。
const arcCenter = Point(
center.x + lineNorm.x * arcRadius,
center.y + lineNorm.y * arcRadius
);
我们将旋转添加到 const startAngle = Math.atan2(lineNorm.y, lineNorm.x);
const endAngle = startAngle + rot;
,然后将startAngle
从arcRadius
沿该新角度移动到新中心。
arcCenter
有了中心的新位置,我们可以更改线的大小并在获得线的长度的同时旋转它。
center.x = arcCenter.x + Math.cos(endAngle) * arcRadius;
center.y = arcCenter.y + Math.sin(endAngle) * arcRadius;
就是这样。该函数可以返回。
const len = lengthOfVec(Point(line.p1.x - line.p2.x, line.p1.y - line.p2.y));
line.p1.x = center.x - Math.cos(endAngle) * len * scale * 0.5;
line.p1.y = center.y - Math.sin(endAngle) * len * scale * 0.5;
line.p2.x = center.x + Math.cos(endAngle) * len * scale * 0.5;
line.p2.y = center.y + Math.sin(endAngle) * len * scale * 0.5;
为显示用法示例,下面的代码段功能相同,但是在此过程中进行了一些优化。
该示例创建一条随机线,然后使用sweepLine函数将其移动。动画不断绘制线条。
}
}
requestAnimationFrame(update);
const ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
function update(timer){
if(w !== innerWidth || h !== innerHeight){
w = canvas.width = innerWidth;
h = canvas.height = innerHeight;
}
jiggle();
sweepLine(line, moveBy,rotateBy, scaleBy);
drawLine(line);
requestAnimationFrame(update);
}
// A Point also defines a vector.
const Point = (x,y) => ({x,y});
const Line = (p1, p2) => ({p1, p2});
const lengthOfVec = vec => (vec.x ** 2 + vec.y ** 2) ** 0.5;
const normalVec = line => { // normalize the line and return a vector
const vec = Point(line.p2.x - line.p1.x, line.p2.y - line.p1.y);
const length = lengthOfVec(vec);
vec.x /= length;
vec.y /= length;
return vec;
}
const rotateVec90 = vec => {
const t = vec.x;
vec.x = - vec.y;
vec.y = t;
return vec;
}
function sweepLine(line, dist, rot, scale){
const center = Point((line.p1.x + line.p2.x) / 2, (line.p1.y + line.p2.y) / 2);
const len = lengthOfVec(Point(line.p1.x - line.p2.x, line.p1.y - line.p2.y));
const lineNorm = normalVec(line);
const norm = rotateVec90(Point(lineNorm.x, lineNorm.y));
if(rot === 0){
const ax = (line.p2.x - center.x) * scale;
const ay = (line.p2.y - center.y) * scale;
center.x += norm.x * dist;
center.y += norm.y * dist;
line.p1.x = center.x - ax
line.p1.y = center.y - ay;
line.p2.x = center.x + ax;
line.p2.y = center.y + ay;
} else {
const arcRadius = dist / rot;
const arcCenter = Point(
center.x - lineNorm.x * arcRadius, center.y - lineNorm.y * arcRadius
);
const endAngle = Math.atan2(lineNorm.y, lineNorm.x) + rot;
var ax = Math.cos(endAngle);
var ay = Math.sin(endAngle);
center.x = arcCenter.x + ax * arcRadius;
center.y = arcCenter.y + ay * arcRadius;
const len = lengthOfVec(Point(line.p1.x - line.p2.x, line.p1.y - line.p2.y));
ax *= len * scale * 0.5;
ay *= len * scale * 0.5;
line.p1.x = center.x - ax;
line.p1.y = center.y - ay;
line.p2.x = center.x + ax;
line.p2.y = center.y + ay;
}
}
function drawLine(line){
ctx.lineWidth = 8;
ctx.lineCap = "round";
ctx.strokeStyle = col;
ctx.beginPath();
ctx.lineTo(line.p1.x, line.p1.y);
ctx.lineTo(line.p2.x, line.p2.y);
ctx.stroke();
}
function createRandomLine(){
const x = Math.random() * w * 0.3 + w * 0.35;
const y = Math.random() * h * 0.3 + h * 0.35;
const len = Math.random() * 40 + 10;
const dir = Math.random() * Math.PI * 2;
return Line(
Point(x - Math.cos(dir) * len * 0.5, y - Math.sin(dir) * len * 0.5),
Point(x + Math.cos(dir) * len * 0.5, y + Math.sin(dir) * len * 0.5)
);
}
// sweep the line randomly needs some settings
var line, rotateBy, moveBy, scaleBy, col, l = 50,s = 70,hue = 0,moveFor = 0; //
function randomize(){
rotateBy = Math.random() * 0.5 - 0.25;
moveBy = Math.random() * 5 + 5;
scaleBy = 1;
moveFor = 200;
line = createRandomLine();
}
function jiggle(){
if(moveFor === 0 ){ randomize() }
rotateBy += (Math.random() - 0.5) * 0.2;
scaleBy = Math.random() < 0.2 ? 1/1.1 : Math.random() < 0.2 ? 1.1 : 1;
moveBy += (Math.random() - 0.5) * 4;
moveFor --;
hue = (hue + 1) % 360;
s = (s + 100 + Math.random() - 0.5) % 100;
l = (l + 100 + Math.random() - 0.5) % 100;
col = "hsl("+hue+","+s+"%,"+l+"%)";
}
canvas { position : absolute; top : 0px; left : 0px; }
答案 2 :(得分:0)
如果对结果满意,可以编写如下函数:
function drawLine(t,r, p1,p2){
//t: translation object
//r: rotation object
//p1: point object for the moveTo() method
//p2: point object for the lineTo() method
//ctx.save();
ctx.beginPath();
ctx.translate(t.x, t.y)
ctx.rotate(r * Math.PI / 180);
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
//ctx.restore();
}
由于您不使用保存和恢复方法,因此我已将其注释掉,但是这些方法非常有用,可以帮助您节省大量计算。