【问题标题】:Edit path-clip to fill svg in right way [closed]编辑路径剪辑以正确方式填充 svg [关闭]
【发布时间】:2020-05-11 07:10:20
【问题描述】:

如何正确注册剪辑路径,以便正确填充线条,即沿着线条而不是像现在这样从上到下。截图展示了一个填充的例子。在codepen,你可以看到整个svg,看看动画是如何工作的(它是通过滚动来控制的)。

截图:

有问题的截图:

现在对其进行剪辑路径(对于所有代码检查codepen):

g.setAttribute('style', `clip-path: polygon(0 0%, 100% 0%, 100% ${progress+0.8}%, 0% ${progress+0.8}%);`)

更新: 如果您提供解决方案,请在我的示例中显示它。由于我的问题是具体的,而且大多数人只是在没有完全查看codepen 上的问题的情况下写。

【问题讨论】:

  • 似乎可以在我的手机(chrome mobile)上使用。好吧,主要是。它还有其他问题,但动画会随心所欲地遵循曲线。
  • @Anthony 我更新了有问题的截图。

标签: javascript html css animation svg


【解决方案1】:

对于每条彩色线条,创建一条来回跟随该线条路线的路径。它的笔画宽度应该足以覆盖最宽的线条。

然后您使用该新行作为<mask> 来显示您的颜色。

基本思想在我对类似问题的回答中有所描述。这个问题是关于模拟动画手写的。但同样的方法也可以解决您的问题。

https://stackoverflow.com/a/37787761/1292848

更新

你在回答之前检查了我的 codepen 吗?

是的,我做到了。那里描述的技术非常适合您的情况。为了证明这一点,这是我自己的 CodePen:

https://codepen.io/PaulLeBeau/pen/RwNOaZg

这是一个概念证明。我只为一小部分路径创建了一个掩码路径。为了演示这个概念,我使用了一个简单的 CSS 动画,而不是实现一个 onscroll 处理程序。

发生的事情应该很明显。您只需根据滚动的距离更改您的 onscroll 处理程序以设置 stroke-dashoffset

如果您不了解 stroke-offset 效果如何为线条长度设置动画,那么整个网络上都有很多教程,这里是 Stack Overflow。例如,CSS-Tricks 就有一个相当不错的:

https://css-tricks.com/svg-line-animation-works/

【讨论】:

  • 我已经更新了我的答案。
  • “我如何为整个动画创建路径,而不仅仅是开始?”与您最初获得设计的方式相同。使用程序来绘制它。
  • “另外,当你转动线时,你会注意到在弯曲点有一个白色三角形。如何解决这个问题?”调整蒙版路径拐角曲线。
  • "如何添加灰色线条直到线条被颜色填充?"在您原来的 CodePen 中,您通过克隆路径/组来做到这一点。你可以在这里做同样的事情。
【解决方案2】:

我花了很长时间(几个小时)研究这个问题,但解决起来并不简单。但我确实有解决方案。也就是说,解决方案也不是那么简单。

注意,蓝色多边形只是用来帮助解释组元素<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]
  }, ...

随着多边形的增长和变得越来越复杂,多边形的每个部分都有一个部分。

这张图应该有助于解释这一点:

还有这个,解释多边形的点数是如何增加的:

【讨论】:

  • 多边形 0 中的 8 个值是因为 4 个点的 x 和 y 坐标。所以它就像 (x1 y1, x2 y2, x3 y3, x4 y4) 并且 index[3,5] 表示更改该数组的索引 3 和 5。即 y2 和 y3 - 这是因为有一次我们在向下或穿过时移动多边形的 1 或 2 个点(如果我们有 index[3,null] 那么这意味着只移动 y2 - 这发生在曲线上)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多