我花了很长时间(几个小时)研究这个问题,但解决起来并不简单。但我确实有解决方案。也就是说,解决方案也不是那么简单。
注意,蓝色多边形只是用来帮助解释组元素<g id="Line_Orange" >的剪辑路径使用什么形状
我没有将它附加到滚动事件,因为我需要一种方法来处理剪辑路径多边形背后的逻辑,并使用我可以获得的最简单设置并允许我启动和停止 setInterval() 到 @ 987654330@ 输出当前的 x 和 y 值等,以计算需要在何处发生转弯等。
完整的例子在这里:https://codepen.io/Alexander9111/pen/eYmbajB
JavaScript 是:
var running = false;
const g = document.querySelector("#Line_Orange");
const g_clone = g.cloneNode(true);
const svg = document.querySelector("svg");
g_clone.id = "Line_Grey";
//svg.appendChild(g_clone);
svg.insertBefore(g_clone, svg.childNodes[0]);
g.setAttribute('clip-path', "polygon(0 0, 0 100, 250 100, 250 0)");
const polygon = document.querySelector("#polygon_mask");
let segment_num = 0;
var temp_arr = [];
var polygon_points_arr = [80, 0, 80, 0];
var polygon_points_str = "80 0 80 0";
const polygon_segments = [
{
n: 0, dir: 1, progress: "y", boost: 1, init_x_y: [80,0], index: [3,5],
points:[80, 0, 80, 250, 250, 250, 250, 0]
},
{
n: 1, dir: 1, progress: "y", boost: 2, init_x_y: [80,100], index: [3,null],
points:[80, 0, 80, 250, 250, 100, 250, 0]
},
{
n: 2, dir: 1, progress: "x", boost: 2, init_x_y: [80,250], index: [4,null],
points:[80, 0, 80, 250, 250, 250, 250, 100, 250, 100, 250, 0]
},
{
n: 3, dir: 1, progress: "x", boost: 1, init_x_y: [250,100], index: [4,6],
points:[80, 0, 80, 250, 450, 250, 450, 100, 250, 100, 250, 0]
},
{
n: 4, dir: 1, progress: "x", boost: 2, init_x_y: [700,100], index: [null,6],
points:[80, 0, 80, 250, 700, 250, 820, 100, 250, 100, 250, 0]
},
{
n: 5, dir: 1, progress: "y", boost: 2, init_x_y: [820,100], index: [null,9],
points:[80, 0, 80, 250, 700, 250, 700, 250, 820, 100, 820, 100, 250, 100, 250, 0]
},
{
n: 6, dir: 1, progress: "y", boost: 1, init_x_y: [820,250], index: [7,9],
points:[80, 0, 80, 250, 700, 250, 700, 250, 820, 100, 820, 100, 250, 100, 250, 0]
},
{
n: 7, dir: 1, progress: "y", boost: 2, init_x_y: [820,600], index: [null,9],
points:[80, 0, 80, 250, 700, 250, 700, 600, 820, 600, 820, 100, 250, 100, 250, 0]
},
{
n: 8, dir: -1, progress: "x", boost: 2, init_x_y: [820,750], index: [null,10],
points:[80, 0, 80, 250, 700, 250, 700, 600, 700, 600, 820, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 9, dir: -1, progress: "x", boost: 1, init_x_y: [700,750], index: [8,10],
points:[80, 0, 80, 250, 700, 250, 700, 600, 700, 600, 820, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 10, dir: -1, progress: "x", boost: 2, init_x_y: [150,600], index: [10,null],
points:[80, 0, 80, 250, 700, 250, 700, 600, 150, 600, 150, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 11, dir: 1, progress: "y", boost: 2, init_x_y: [0,600], index: [11,null],
points:[80, 0, 80, 250, 700, 250, 700, 600, 0, 600, 0, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 12, dir: 1, progress: "y", boost: 1, init_x_y: [0,750], index: [11,13],
points:[80, 0, 80, 250, 700, 250, 700, 600, 0, 600, 0, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
}
];
var progressY = 0;
var progressX = 80;
const velocity = 1;
var boost = 1;
var direction = 1;
var timeInterval; //to be started at a later time
function myTimer() {
//console.log(progress);
direction = polygon_segments[segment_num].dir;
polygon_points_arr = polygon_segments[segment_num].points;
//console.log("null == 0", null == 0);
var progress = polygon_segments[segment_num].progress == "x" ? progressX : progressY;
var first_index = polygon_segments[segment_num].index[0];
var second_index = polygon_segments[segment_num].index[1];
if (first_index != null){
polygon_points_arr[first_index] = progress;
}
if (second_index != null){
polygon_points_arr[second_index] = progress;
}
polygon_points_arr.map((child, index) => {
if (index % 2 == 0 && index < polygon_points_arr.length - 1){
return child + ",";
} else {
return child
}
});
temp_arr = polygon_points_arr.map((el, index, arr) => {
if ((index + 1) % 2 == 0 && index < arr.length - 1){
return el + ",";
} else {
return el;
}
});
polygon_points_str = temp_arr.join(" ");
console.log(polygon_points_str);
function incrementAndSetValues(){
segment_num +=1;
boost = polygon_segments[segment_num].boost;
progressX = polygon_segments[segment_num].init_x_y[0];
progressY = polygon_segments[segment_num].init_x_y[1];
}
if (progressY>= 10000) {
clearInterval(timeInterval);
} else {
if (segment_num == 0) {
progressY += (velocity * boost * direction);
if (progressY >= 100) {
incrementAndSetValues()
}
} else if (segment_num == 1){
progressY += (velocity * boost * direction);
if (progressY >= 250) {
incrementAndSetValues()
}
console.log(segment_num);
} else if (segment_num == 2){
progressX += (velocity * boost * direction);
if (progressX >= 250) {
incrementAndSetValues()
}
} else if (segment_num == 3){
progressX += (velocity * boost * direction);
if (progressX >= 700) {
incrementAndSetValues()
}
} else if (segment_num == 4){
progressX += (velocity * boost * direction);
if (progressX >= 820) {
incrementAndSetValues()
}
} else if (segment_num == 5){
progressY += (velocity * boost * direction);
if (progressY >= 250) {
incrementAndSetValues()
}
} else if (segment_num == 6){
progressY += (velocity * boost * direction);
if (progressY >= 600) {
incrementAndSetValues()
}
} else if (segment_num == 7){
progressY += (velocity * boost * direction);
if (progressY >= 750) {
incrementAndSetValues()
}
} else if (segment_num == 8){
progressX += (velocity * boost * direction);
if (progressX <= 700) {
incrementAndSetValues()
}
} else if (segment_num == 9){
progressX += (velocity * boost * direction);
if (progressX <= 150) {
incrementAndSetValues()
}
} else if (segment_num == 10){
progressX += (velocity * boost * direction);
if (progressX <= 0) {
incrementAndSetValues()
}
} else if (segment_num == 11){
progressY += (velocity * boost * direction);
if (progressY >= 750) {
incrementAndSetValues()
}
} else if (segment_num == 12){
progressY += (velocity * boost * direction);
}
}
//console.log(segment_num);
g.setAttribute('clip-path', `polygon(${polygon_points_str})`);
polygon.setAttribute('points', polygon_points_str);
}
function myStopFunction() {
console.log("stop X,Y", progressX, progressY);
document.querySelector("#start").removeAttribute('disabled', true);
document.querySelector("#stop").setAttribute('disabled', true);
clearInterval(timeInterval);
running = false;
}
function myStartFunction() {
timeInterval = setInterval(myTimer, 10);
document.querySelector("#start").setAttribute('disabled', true);
document.querySelector("#stop").removeAttribute('disabled', true);
running = true;
}
document.querySelector("#start").addEventListener('click', myStartFunction);
document.querySelector("#stop").addEventListener('click', myStopFunction);
document.addEventListener('keydown', function(e){
console.log(e.code);
if (e.code == "Enter"){
if (running){
myStopFunction();
} else {
myStartFunction();
}
}
});
document.querySelector("#reset").addEventListener('click', function(){
progressY = 0.00;
progressX = 0.00;
segment_num = 0;
myTimer();
document.querySelector("#start").removeAttribute('disabled', true);
document.querySelector("#stop").removeAttribute('disabled', true);
});
document.addEventListener('DOMContentLoaded',
function(){
const g_grey = document.querySelector("#Line_Grey");
//console.log(g_grey);
const grey_paths = g_grey.querySelectorAll("path, polygon");
for (i = 0; i< grey_paths.length; i++) {
//console.log(grey_paths[i]);
if (grey_paths[i].getAttribute('fill') == "none"){
//do nothing
} else if (grey_paths[i].getAttribute('fill') != "#bbbbbb"){
//must be orange, change to grey
grey_paths[i].setAttribute('fill',"#bbbbbb");
}
}
myTimer();
}, false);
而 JavaScript 最重要的部分就是这个数组:
const polygon_segments = [
{
n: 0, dir: 1, progress: "y", boost: 1, init_x_y: [80,0], index: [3,5],
points:[80, 0, 80, 250, 250, 250, 250, 0]
}, ...
随着多边形的增长和变得越来越复杂,多边形的每个部分都有一个部分。
这张图应该有助于解释这一点:
还有这个,解释多边形的点数是如何增加的: