类似于 Illustrator 的 SVG 混合

问题描述 投票:0回答:1

我正在尝试混合两个矩形。一种具有白色填充,一种具有黑色填充。我已附上迄今为止所拥有的内容,但这与我希望实现的结果完全不同。我已阅读了几篇论坛帖子,但找不到任何帮助。有人可以建议去哪里寻找或提供任何帮助吗?

我试过他跟随

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rect transition</title>
</head>
<body>
    <svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">        
        <defs>
            <filter id="blurFilter">                
                <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
            </filter>
        </defs>
                
        <rect x="10" y="10" width="1in" height="0.5in" fill="white" filter="url(#blurFilter)" />                
        <rect x="20" y="20" width="1in" height="0.5in" fill="black" filter="url(#blurFilter)" />
    </svg>
</body>
</html>

我期待看到这个
blend rectangles

编辑:这是最近的尝试,但仍然不是我所期望的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Another try</title>
</head>
<body>
    <svg width="500" height="300" xmlns="http://www.w3.org/2000/svg">        
        <defs>
            <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" style="stop-color:white; stop-opacity:1" />
                <stop offset="100%" style="stop-color:black; stop-opacity:1" />
            </linearGradient>            
            <filter id="blurFilter" x="0" y="0" width="200%" height="200%">                
                <feGaussianBlur stdDeviation="8" />
            </filter>
        </defs>                
        <rect x="50" y="100" width="80" height="40" fill="white" />                
        <rect x="150" y="125" width="120" height="60" fill="url(#grad)" filter="url(#blurFilter)" />                     <rect x="250" y="150" width="160" height="80" fill="black" />
    </svg>
</body>
</html>

svg transition blend
1个回答
0
投票

恐怕没有简单的方法可以复制 Adobe Illustrators 混合工具。

虽然 SVG 过滤器在某些情况下可能能够获得类似的结果,但它们只能渲染基于一个元素的过滤结果。

通过 JS 克隆元素

如前所述,您可以研究 JavaScript 解决方案。
这种方法基于检索宽度、高度、x、y、填充等属性,并最终创建具有插值的克隆元素:

let intermediates = 3;
interpolateRects(r1, r2, intermediates);

function interpolateRects(el1, el2, intermediates = 10) {
  //el1
  let style1 = window.getComputedStyle(el1);
  let x1 = el1.x.baseVal.value;
  let y1 = el1.y.baseVal.value;
  let width1 = el1.width.baseVal.value;
  let height1 = el1.height.baseVal.value;
  let col1Arr = style1.fill
    .replace(/rgb\(|\)/g, "")
    .split(", ")
    .map(Number);

  //el2
  let style2 = window.getComputedStyle(el2);
  let x2 = el2.x.baseVal.value;
  let y2 = el2.y.baseVal.value;
  let width2 = el2.width.baseVal.value;
  let height2 = el2.height.baseVal.value;
  let col2Arr = style2.fill
    .replace(/rgb\(|\)/g, "")
    .split(", ")
    .map(Number);

  //create intermediate/interpolated clones
  for (let i = 1; i < intermediates+1; i++) {
    // interpolation
    let t = 1 /(intermediates+1) * i;
    let xM = interpolateVals(x1, x2, t);
    let yM = interpolateVals(y1, y2, t);
    let wM = interpolateVals(width1, width2, t);
    let hM = interpolateVals(height1, height2, t);
    let colM = col1Arr.map((col, c) => {
      return ( interpolateVals(col, col2Arr[c], t) );
    });
    
    
    //clone element
    let clone = el1.cloneNode(true);
    clone.removeAttribute('id')
    clone.setAttribute('x', xM)
    clone.setAttribute('y', yM)
    clone.setAttribute('width', wM)
    clone.setAttribute('height', hM)
    clone.setAttribute('fill', `rgb(${colM.join(',')})`)
    
    //add elements
    el1.parentNode.insertBefore(clone, el2)
  }
}

/**
 * linear interpolation helper
 */
function interpolateVals(val1, val2, t) {
  return (val2 - val1) * t + val1;
}
body{
  background: #ccc;
}
    <svg viewBox="0 0 200 200">        
        <rect id="r1" x="10" y="10" width="1in" height="0.5in" fill="white"  />                
        <rect id="r2" x="75" y="50" width="1in" height="1in" fill="black"  />
    </svg>

伪混合依赖于中间体的数量
为了获得顺利的结果,您可能需要 100 多个步骤

let intermediates = 100;
interpolateRects(r1, r2, intermediates);

function interpolateRects(el1, el2, intermediates = 10) {
  //el1
  let style1 = window.getComputedStyle(el1);
  let x1 = el1.x.baseVal.value;
  let y1 = el1.y.baseVal.value;
  let width1 = el1.width.baseVal.value;
  let height1 = el1.height.baseVal.value;
  let col1Arr = style1.fill
    .replace(/rgb\(|\)/g, "")
    .split(", ")
    .map(Number);

  //el2
  let style2 = window.getComputedStyle(el2);
  let x2 = el2.x.baseVal.value;
  let y2 = el2.y.baseVal.value;
  let width2 = el2.width.baseVal.value;
  let height2 = el2.height.baseVal.value;
  let col2Arr = style2.fill
    .replace(/rgb\(|\)/g, "")
    .split(", ")
    .map(Number);

  //create intermediate/interpolated clones
  for (let i = 1; i < intermediates+1; i++) {
    // interpolation
    let t = 1 /(intermediates+1) * i;
    let xM = interpolateVals(x1, x2, t);
    let yM = interpolateVals(y1, y2, t);
    let wM = interpolateVals(width1, width2, t);
    let hM = interpolateVals(height1, height2, t);
    let colM = col1Arr.map((col, c) => {
      return ( interpolateVals(col, col2Arr[c], t) );
    });
    
    
    //clone element
    let clone = el1.cloneNode(true);
    clone.removeAttribute('id')
    clone.setAttribute('x', xM)
    clone.setAttribute('y', yM)
    clone.setAttribute('width', wM)
    clone.setAttribute('height', hM)
    clone.setAttribute('fill', `rgb(${colM.join(',')})`)
    
    //add elements
    el1.parentNode.insertBefore(clone, el2)
  }
}

/**
 * linear interpolation helper
 */
function interpolateVals(val1, val2, t) {
  return (val2 - val1) * t + val1;
}
body{
  background: #ccc;
}
<svg viewBox="0 0 200 200">        
        <rect id="r1" x="10" y="10" width="1in" height="0.5in" fill="white"  />                
        <rect id="r2" x="75" y="50" width="1in" height="1in" fill="black"  />
    </svg>

冷知识:这实际上是 Illustrator 早期版本的方式(<7) worked in the 1990ies to emulate gradients.

显然,您可能需要添加其他属性,如

stroke
fill-opacity
才能获得所需的结果。

<path>
和其他元素呢?

当然,这些元素是兼容的,您可以扩展这个基本概念。但匹配各种元素和属性值肯定需要付出很大的努力。 (公平地说,当元素的几何形状不兼容时,Illustrator 的混合工具也会失败)。

© www.soinside.com 2019 - 2024. All rights reserved.