编辑
这是一个正确应用长度和模型但没有正确定位模型的新版本。我想这可能会有所帮助。
http://codepen.io/pixelass/pen/78f9e97579f99dc4ae0473e33cae27d5?editors=001
我有 2 个画布实例
- 模型
- 结果
在模型视图上,用户可以拖动手柄来修改模型结果视图应该将模型应用于每个段(相对)
这只是分形曲线的基本 l 系统逻辑,尽管我在将模型应用于段时遇到问题。
见下图:红线应该复制模型,但我不知道如何正确应用逻辑
我在这里有一个演示版:http: //codepen.io/pixelass/pen/c4d7650af7ce4901425b326ad7a4b259
ES6
// simplify Math
'use strict';
Object.getOwnPropertyNames(Math).map(function(prop) {
window[prop] = Math[prop];
});
// add missing math functions
var rad = (degree)=> {
return degree * PI / 180;
};
var deg = (radians)=> {
return radians * 180 / PI;
};
// get our drawing areas
var model = document.getElementById('model');
var modelContext = model.getContext('2d');
var result = document.getElementById('result');
var resultContext = result.getContext('2d');
var setSize = function setSize() {
model.height = 200;
model.width = 200;
result.height = 400;
result.width = 400;
};
// size of the grabbing dots
var dotSize = 5;
// flag to determine if we are grabbing a point
var grab = -1;
// set size to init instances
setSize();
//
var iterations = 1;
// define points
// this only defines the initial model
var returnPoints = function returnPoints(width) {
return [{
x: 0,
y: width
}, {
x: width / 3,
y: width
}, {
x: width / 2,
y: width / 3*2
}, {
x: width / 3 * 2,
y: width
}, {
x: width,
y: width
}];
};
// set initial state for model
var points = returnPoints(model.width);
// handle interaction
// grab points only if hovering
var grabPoint = function grabPoint(e) {
var X = e.layerX;
var Y = e.layerY;
for (var i = 1; i < points.length - 1; i++) {
if (abs(X - points[i].x) < dotSize && abs(Y - points[i].y) < dotSize) {
model.classList.add('grabbing');
grab = i;
}
}
};
// release point
var releasePoint = function releasePoint(e) {
if (grab > -1) {
model.classList.add('grab');
model.classList.remove('grabbing');
}
grab = -1;
};
// set initial state for result
// handle mouse movement on the model canvas
var handleMove = function handleMove(e) {
// determine current mouse position
var X = e.layerX;
var Y = e.layerY;
// clear classes
model.classList.remove('grabbing');
model.classList.remove('grab');
// check if hovering a dot
for (var i = 1; i < points.length - 1; i++) {
if (abs(X - points[i].x) < dotSize && abs(Y - points[i].y) < dotSize) {
// indicate grabbable
model.classList.add('grab');
}
}
// if grabbing
if (grab > -1) {
// indicate grabbing
model.classList.add('grabbing');
// modify dot on the model canvas
points[grab] = {
x: X,
y: Y
};
// modify dots on the result canvas
drawSegment({
x: points[grab - 1].x,
y: points[grab - 1].y
}, {
x: X,
y: Y
});
}
};
let m2 = points[1].x / points[4].x
let m3 = points[2].x / points[4].x
let m4 = points[3].x / points[4].x
let n2 = points[1].y / points[4].y
let n3 = points[2].y / points[4].y
let n4 = points[3].y / points[4].y
var drawSegment = function drawSegment(start, end) {
var dx = end.x - start.x
var dy = end.y - start.y
var dist = sqrt(dx * dx + dy * dy)
var angle = atan2(dy, dx)
let x1 = end.x
let y1 = end.y
let x2 = round(cos(angle) * dist)
let y2 = round(sin(angle) * dist)
resultContext.srtokeStyle = 'red'
resultContext.beginPath()
resultContext.moveTo(x1, y1)
resultContext.lineTo(x2, y2)
resultContext.stroke()
m2 = points[1].x / points[4].x
m3 = points[2].x / points[4].x
m4 = points[3].x / points[4].x
n2 = points[1].y / points[4].y
n3 = points[2].y / points[4].y
n4 = points[3].y / points[4].y
};
var drawDots = function drawDots(points) {
// draw dots
for (var i = 1; i < points.length - 1; i++) {
modelContext.lineWidth = 4; //
modelContext.beginPath();
modelContext.strokeStyle = 'hsla(' + 360 / 5 * i + ',100%,40%,1)';
modelContext.fillStyle = 'hsla(0,100%,100%,1)';
modelContext.arc(points[i].x, points[i].y, dotSize, 0, 2 * PI);
modelContext.stroke();
modelContext.fill();
}
};
var drawModel = function drawModel(ctx, points, n) {
var dx = points[1].x - points[0].x
var dy = points[1].y - points[0].y
var dist = sqrt(dx * dx + dy * dy)
var angle = atan2(dy, dx)
let x1 = points[1].x
let y1 = points[1].y
let x2 = round(cos(angle) * dist)
let y2 = round(sin(angle) * dist)
ctx.strokeStyle = 'hsla(0,0%,80%,1)';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(points[0].x,
points[0].y)
ctx.lineTo(points[1].x * m2,
points[1].y * n2)
ctx.lineTo(points[1].x * m3,
points[1].y * n3)
ctx.lineTo(points[1].x * m4,
points[1].y * n4)
ctx.lineTo(points[1].x,
points[1].y)
ctx.stroke();
ctx.strokeStyle = 'hsla(100,100%,80%,1)';
ctx.beginPath();
ctx.moveTo(points[0].x,
points[0].y)
ctx.lineTo(points[1].x,
points[1].y)
ctx.stroke()
if (n > 0 ) {
drawModel(resultContext, [{
x: points[0].x,
y: points[0].y
}, {
x: points[1].x * m2,
y: points[1].y * n2
}], n - 1);
drawModel(resultContext, [{
x: points[1].x * m2,
y: points[1].y * n2
}, {
x: points[1].x * m3,
y: points[1].y * n3
}], n - 1);
/*
drawModel(resultContext, [{
x: points[1].x * m3,
y: points[1].y * m3
}, {
x: points[1].x * m4,
y: points[1].y * n4
}], n - 1);
drawModel(resultContext, [{
x: points[1].x * m4,
y: points[1].y * m4
}, {
x: points[1].x,
y: points[1].y
}], n - 1);*/
} else {
ctx.strokeStyle = 'hsla(0,100%,50%,1)';
ctx.beginPath();
ctx.moveTo(points[0].x,
points[0].y)
ctx.lineTo(points[1].x * m2,
points[1].y * n2)
ctx.lineTo(points[1].x * m3,
points[1].y * n3)
ctx.lineTo(points[1].x * m4,
points[1].y * n4)
ctx.lineTo(points[1].x,
points[1].y)
ctx.stroke();
}
};
var draw = function draw() {
// clear both screens
modelContext.fillStyle = 'hsla(0,0%,100%,.5)';
modelContext.fillRect(0, 0, model.width, model.height);
resultContext.fillStyle = 'hsla(0,0%,100%,1)';
resultContext.fillRect(0, 0, result.width, result.height);
// draw model
drawModel(modelContext, [{
x: 0,
y: 200
}, {
x: 200,
y: 200
}]);
drawModel(resultContext, [{
x: 0,
y: 400
}, {
x: 400,
y: 400
}],iterations);
// draw the dots to indicate grabbing points
drawDots(points);
// redraw
requestAnimationFrame(draw);
};
window.addEventListener('resize', setSize);
model.addEventListener('mousemove', handleMove);
model.addEventListener('mousedown', grabPoint);
window.addEventListener('mouseup', releasePoint);
setSize();
draw();