我正在尝试混合两个矩形。一种具有白色填充,一种具有黑色填充。我已附上迄今为止所拥有的内容,但这与我希望实现的结果完全不同。我已阅读了几篇论坛帖子,但找不到任何帮助。有人可以建议去哪里寻找或提供任何帮助吗?
我试过他跟随
<!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>
编辑:这是最近的尝试,但仍然不是我所期望的
<!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>
恐怕没有简单的方法可以复制 Adobe Illustrators 混合工具。
虽然 SVG 过滤器在某些情况下可能能够获得类似的结果,但它们只能渲染基于一个元素的过滤结果。
如前所述,您可以研究 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 的混合工具也会失败)。