使用jQuery更改路径上的SVG描边

3

我已将SVG图像设置为div的背景。现在,我想使用jQuery每隔x秒更改特定路径的描边。我看过一个示例(点击这里),基本上就是这样做的。

这是我的jQuery代码:

$(document).ready(function(){

  var _currStroke = 'ffa500';

  var svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5" /> </svg>';

  var encoded = window.btoa(svg);
  $("nav").css("background", "url(data:image/svg+xml;base64,"+encoded+")");

  /* change stroke color every x seconds (atm: 3) */
  var changingTimeInMS = 3000;
  var currentColor = $("outline_path").attr('stroke');
  setInterval(function() {    

    var lastIndex = changeStrokeColor(currentColor, lastIndex);

  }, changingTimeInMS);

});

function changeStrokeColor(currentColor, lastIndex) {

    var colors = ['32cd32',  /* limegreen */
                '00ffff',  /* cyan */
                'ffa500',  /* orange */
                'ffffff']; /* white */

    $.each(colors, function(lastIndex) {
      if(colors[lastIndex] == currentColor) {
          return true;
      }
      $("#outline_path").attr('style', "stroke:'+this+'");
      $("#nav").css('border-color', this);

      lastIndex++;
      return lastIndex;
});

}

让我们快速浏览一下:

  1. 我定义了一个描边颜色(_currStroke = 'ffa500')
  2. 我编码 SVG 并将其设置为导航的背景
  3. 请注意 SVG 路径:它有一个 id(#'outline_path')和样式:style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
  4. 将当前描边颜色保存在变量中(currentColor)
  5. 每隔 changeTimeInMS 秒调用 changeStrokeColor 函数
  6. 将 changeStrokeColor 的返回值保存在变量中(lastIndex)
  7. changeStrokeColors 需要两个变量:描边的当前颜色和最后一个索引(第一次调用 changeStrokeColors 可能吗?lastIndex 还没有被声明,但我不能将其设置为 0,否则它会每 x 秒重置一次)
  8. 遍历颜色数组;如果当前颜色等于我们目前所在的索引,则跳过它(return true)并继续执行以下操作:
  9. 搜索具有 id outline_path 的路径,并将描边更改为我们在迭代中的当前元素
  10. 还要将导航边框颜色更改为该颜色
  11. 增加 lastIndex 并返回它

我可以通过更改 var _currStroke 来更改颜色,但“每隔 x 秒执行一次”的事情根本不起作用。请注意,我是 JS(和 SVG)的初学者。任何帮助都将不胜感激。

我制作了一个 CodePen 来说明:CodePen

1个回答

4

演示实时操作

你的代码存在很多问题,
我会尽力解决它们:

  1. 您使用了HTML元素<nav>,但在您的代码中您试图定位某个ID: $("#nav").css( 您实际上想要的选择器是您已经在代码中使用的那个,也就是$("nav")

  2. 您正在将SVG元素转换为base64数据图像
    一旦它被转换为图像,它就不再是一个您可以操作的活动对象**,因此在使用它之前,您基本上需要重新构建一个具有不同颜色的新图像。否则,您可以探索如何使用SVG <pattern>

  3. 您在数组中设置了无效颜色'32cd32'不是HEX颜色,而'#32cd32'是。

  4. $("outline_path")不是ID选择器见•1,但无论如何,现在定位它为时已晚,因为您的SVG现在是一个base64数据图像见•2

  5. 没有必要记住 lastIndex 颜色并在$.each中再次迭代您的colors数组,只需使用一个数组计数器指针,增加该计数器而不是循环您增加的 Counter:++counter%totColors

  6. .attr('style', "stroke:'+this+'")是错误的字符串 + var拼接。应该是这样的:.attr('style', "stroke:'"+ this +"'"),其中双引号内都是字符串,外部是+连接变量。

  7. 您需要预先创建所有图像,以防止间隔开始滴答声时出现空白间隙(正在创建图像)。

  8. 您将无法将transition: stroke .4s ease;设置为图像。抱歉。您可能想探索在淡化背景图像时的其他技巧(涉及2个元素)。例1 例2 例3

  9. 不要在间隔内部再次创建变量。改为使用全局变量。

  10. 创建一个将返回新图像的函数。

以下是根据您的想法和最初的代码进行重建的尝试:
var $nav = $("nav"), // Cache your selectors
  colors = [
  '#00ffff',  // cyan
  '#32cd32',  // limegreen
  '#ffa500',  // orange
  '#ffffff',  // white
  'red'
  ], 
  totColors = colors.length, // How many colors?
  counter = 0;               // Colors Array loop counter

function newSvg(co){
  var svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+ co +'; opacity: 0.5" /> </svg>';
  return "data:image/svg+xml;base64,"+ window.btoa(svg);
}

function changeStrokeColor() {
  var co = colors[++counter%totColors]; // Increase and Loop colors
  $nav.css({
    borderColor: co,
    background : "url("+ newSvg(co) +")"
  });
}  

for(var i=0; i<totColors; i++){ // Preload all backgrounds
  var img = new Image();
  img.src = newSvg(colors[i]);
}

$(function(){ // DOM ready
  $nav.css("background", "url("+ newSvg( colors[counter] ) +")" );
  setInterval(changeStrokeColor, 1000);
});

哇,非常感谢。我想我会花一些时间阅读手册。现在性能怎么样?重新创建一张图片会不会减慢页面速度? - sqe
@sqe 不,使用 new Image 创建的图像是从浏览器缓存中获取的。无论如何,我建议探索 <pattern>,这样你就能做更多酷炫的事情,不仅仅是应用淡入淡出效果。 - Roko C. Buljan
好的,我会看一下。谢谢你的时间。 - sqe
1
@sqe 不用谢。SVG有很多属性和特性,有点复杂...就像一个独立的世界,但是一旦你掌握了它们... :) “在黑暗的地方,我们发现自己,一点点更多的知识照亮了我们的道路。”-尤达 - Roko C. Buljan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接