我有一個問題,我的兩個 svg 具有相同的點數,但是當我播放影片時出現了問題,兩個 svg 靠得很近,但是影片突然跳出來而且不對,在第一個 svg 變為第二個之前,會出現一個奇怪的形狀。
我正在 Adob??e XD 中制作 svg。這是代碼:
<svg id="morph" viewBox="0 0 1920 540">
<path class="morph" d="m864.216 135.95 36.39 41.917S780.519 307.11 1078.914 373.479s221.979-87.327 221.979-87.327l32.75-34.931s25.473 101.3 207.422 34.931 440.314 150.2 411.2 380.744S34.528 576.079 34.528 576.079s-3.64-429.647 342.063-509.987 272.923 174.653 487.623 69.861"/>
</svg>
<script>
var overlay = document.getElementById('morph');
var morphing = anime({
targets: '.morph',
d: [
{value : "m864.216 135.95 36.39 41.917S780.519 307.11 1078.914 373.479s221.979-87.327 221.979-87.327l32.75-34.931s25.473 101.3 207.422 34.931 440.314 150.2 411.2 380.744S34.528 576.079 34.528 576.079s-3.64-429.647 342.063-509.987 272.923 174.653 487.623 69.861"},
{value: "M2.49 576.483S20.535 398.736 122.472 239.61s236.674-199.127 302-217.883c176.407-41.244 334 45.685 334 45.685l340 233.7s172 105.427 280 119.484 322 12.3 322 12.3 118 5.271 160 61.5 56 89.613 62 117.727S2.49 576.483 2.49 576.483Z"},
],
duration: 1200,
loop: false,
easing: 'easeInOutQuint'
})
</script>
uj5u.com熱心網友回復:
您的路徑仍然需要一些優化才能完全兼容插值。
大多數影片庫都試圖使路徑在某種程度上兼容(例如,通過將它們轉換為像flubber.js中那樣的多邊形)。
但通常你會得到最好的結果手動清理你的路徑。
| 步驟1 | 第2步 |
|---|---|
| 米 864.216 135.95 | 米 2.49 576.483 |
| l 36.39 41.917 | 小號 20.535 398.736 122.472 239.61 |
| 小號 780.519 307.11 1078.914 373.479 | s 236.674 -199.127 302-217.883 |
| s 221.979 -87.327 221.979 -87.327 | c 176.407 -41.244 334 45.685 334 45.685 |
| l 32.75 -34.931 | l 340 233.7 |
| s 25.473 101.3 207.422 34.931 | 172 105.427 280 119.484 |
| 440.314 150.2 411.2 380.744 | 322 12.3 322 12.3 |
| 小號 34.528 576.079 34.528 576.079 | 118 5.271 160 61.5 |
| 小號 -3.64 -429.647 342.063-509.987 | 56 89.613 62 117.727 |
| s 272.923 174.653 487.623 69.861 | 小號 2.49 576.483 2.49 576.483 |
| Z |
您的命令型別也需要兼容。
例如,第二個影片步驟只有一個l(lineTo) 命令和一個Z(closePath) 在第一個路徑中丟失。
不幸的是,您不能確定您的編輯器/圖形應用程式會輸出相同的命令,因為它可能決定使用速記命令(例如水平 lineTos 的 h )來縮小標記。
規范化d為一組減少的命令
這將通過將路徑資料轉換為 M、C、L 和 Z 命令來簡化進一步的調整。
我正在使用Jarek Foksa 的 getPathData polyfill。
path.getPathData({normalize: true});
{normalize: true}引數還將所有命令轉換為絕對坐標。
將 L 命令轉換為 C
通過像這樣重復 x/y 坐標,您可以輕松地將L命令轉換為C曲線。
L 901 178
至:
C 901 178 901 178 901 178
調整M起點
將起點設定為最左邊的角/點。因此,您的路徑將使用視覺參考點進行插值。否則你可能會得到奇怪的翻轉過渡。
使用絕對和規范化命令也更容易更改M路徑。您還將在代碼段中找到一個輔助函式
(1. 路徑資料塊 => 將附加在第二個塊之后)
M 864 136 (舊起點 => 將被洗掉)
C 901 178 901 178 901 178
C 901 178 781 307 1079 373
C 1377 440 1301 286 1301 286
C 1334 251 1334 251 1334 251
C 1334 251 1359 353 1541 286
C 1723 220 1981 436 1952 667
C 1923 897 35 576 35 576 => 將成為新的 M xy 坐標
(2.路徑資料塊)
C 35 576 31 146 377 66
C 722 -14 650 241 864 136
(3.路徑資料塊:closePath)
Z
結果:
M 35 576
C 35 576 31 146 377 66
C 722 -14 650 241 864 136
C 901 178 901 178 901 178
C 901 178 781 307 1079 373
C 1377 440 1301 286 1301 286
C 1334 251 1334 251 1334 251
C 1334 251 1359 353 1541 286
C 1723 220 1981 436 1952 667
C 1923 897 35 576 35 576
Z
路徑方向
在您的情況下,兩條路徑都有順時針方向。
如果您遇到奇怪的翻轉過渡,您可以嘗試反轉路徑方向。
您可以使用@enxaneta 的出色 codepen 示例或
Svg 路徑指揮官庫。
示例 1:規范化和更改起點(包括助手)
顯示代碼片段
let svgNorm = document.querySelectorAll('.svgNorm');
svgNorm.forEach(function(svg) {
let svgPaths = svg.querySelectorAll('path');
normalizePaths(svgPaths, 0, true);
})
let orig1 = document.querySelector('.orig1');
let orig2 = document.querySelector('.orig2');
let path1 = document.querySelector('.morph1');
let path2 = document.querySelector('.morph2');
//shift starting point
shiftSvgStartingPoint(path1, 7);
//show starting points
addMarkers(orig1);
addMarkers(orig2);
addMarkers(path1);
addMarkers(path2);
function normalizePaths(paths, decimals = 1, convertLineto = false) {
paths.forEach(function(path, i) {
let pathData = path.getPathData({
normalize: true
});
pathData.forEach(function(com) {
let [type, values] = [com['type'], com['values']];
values.forEach(function(coord, c) {
com['values'][c] = (com['values'][c]).toFixed(decimals)
})
let [x, y] = [com['values'][0], com['values'][1]];
if (type == 'L' && convertLineto) {
com['type'] = 'C';
com['values'] = [x, y, x, y, x, y];
}
})
path.setPathData(pathData)
})
}
function shiftSvgStartingPoint(path, offset) {
let pathData = path.getPathData({
normalize: true
});
let pathDataL = pathData.length;
//exclude Z/z (closepath) command if present
let lastCommand = (pathData[pathDataL - 1]['type']);
let trimR = 0;
if (lastCommand == 'Z') {
trimR = 1;
}
let newStartIndex = offset 1 < pathData.length - 1 ? offset 1 : pathData.length - 1 - trimR;
let newPathData = pathData;
let newPathDataL = newPathData.length;
// slice array to reorder
let newPathDataStart = newPathData.slice(newStartIndex);
let newPathDataEnd = newPathData.slice(0, newStartIndex);
// remove original M
newPathDataEnd.shift();
let newPathDataEndL = newPathDataEnd.length;
let newPathDataEndLastValues = newPathDataEnd[newPathDataEndL - 1]['values'];
let newPathDataEndLastXY = [newPathDataEndLastValues[newPathDataEndLastValues.length - 2],
newPathDataEndLastValues[newPathDataEndLastValues.length - 1]
];
//remove z(close path) from original pathdata array
if (trimR) {
newPathDataStart.pop();
newPathDataEnd.push({
'type': 'Z',
'values': []
});
}
// prepend new M command and concatenate array chunks
newPathData = [{
'type': 'M',
'values': newPathDataEndLastXY
}].concat(newPathDataStart).concat(newPathDataEnd);
// update path's d property
path.setPathData(newPathData);
return path;
}
testInterpolation(path1, path2);
function testInterpolation(path1, path2) {
path1.addEventListener('click', function(e) {
if (!path1.getAttribute('style')) {
path1.setAttribute('style', `d:path("${path2.getAttribute('d')}")`)
} else {
path1.removeAttribute('style');
}
})
}
function addMarkers(path) {
let svg = path.closest('svg');
let markerDef = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
let marker =
`<marker id="circle" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10%" markerHeight="10%"
orient="auto-start-reverse">
<circle cx="5" cy="5" r="5" fill="green" />
</marker>`;
markerDef.innerHTML = marker;
svg.insertBefore(markerDef, svg.childNodes[0]);
path.setAttribute('marker-start', 'url(#circle)');
}
svg {
display: inline-block;
width: 30%;
overflow: visible;
border: 1px solid #ccc;
margin-right: 5%;
}
.row {
margin-top: 4em;
}
path {
opacity: 0.5;
transition: 0.5s;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/path-data-polyfill.min.js"></script>
<div>
<p>Green points illustrate starting points</p>
<svg viewBox="0 0 1920 540">
<path class="orig1" d="
m 864.216 135.95
l 36.39 41.917
S 780.519 307.11 1078.914 373.479
s 221.979 -87.327 221.979 -87.327
l 32.75 -34.931
s 25.473 101.3 207.422 34.931
s 440.314 150.2 411.2 380.744
S 34.528 576.079 34.528 576.079
s -3.64 -429.647 342.063-509.987
s 272.923 174.653 487.623 69.861
z" />
</svg>
<svg viewBox="0 0 1920 540">
<path class="orig2" d="
M 2.49 576.483
S 20.535 398.736 122.472 239.61
s 236.674 -199.127 302-217.883
c 176.407 -41.244 334 45.685 334 45.685
l 340 233.7
s 172 105.427 280 119.484
s 322 12.3 322 12.3
s 118 5.271 160 61.5
s 56 89.613 62 117.727
S 2.49 576.483 2.49 576.483
Z" />
</svg>
</div>
<div class="row">
<svg class="svgNorm" viewBox="0 0 1920 540">
<path class="morph1"
d="
m 864.216 135.95
l 36.39 41.917
S 780.519 307.11 1078.914 373.479
s 221.979 -87.327 221.979 -87.327
l 32.75 -34.931
s 25.473 101.3 207.422 34.931
s 440.314 150.2 411.2 380.744
S 34.528 576.079 34.528 576.079
s -3.64 -429.647 342.063-509.987
s 272.923 174.653 487.623 69.861
z" />
</svg>
<svg class="svgNorm" viewBox="0 0 1920 540">
<path class="morph2"
d="
M 2.49 576.483
S 20.535 398.736 122.472 239.61
s 236.674 -199.127 302-217.883
c 176.407 -41.244 334 45.685 334 45.685
l 340 233.7
s 172 105.427 280 119.484
s 322 12.3 322 12.3
s 118 5.271 160 61.5
s 56 89.613 62 117.727
S 2.49 576.483 2.49 576.483
Z" />
</svg>
<p>Click on the left path to see morphing animation. <br />Inspect this path in DevTools to get new compatible path data.</p>
</div>
示例 2:使用anime.js 變形優化路徑
顯示代碼片段
var morphing = anime({
targets: ".morph",
d: [
{
value:
"M 2 576 C 2 576 21 399 122 240 C 224 80 359 40 424 22 C 601 -20 758 67 758 67 C 1098 301 1098 301 1098 301 C 1098 301 1270 407 1378 421 C 1486 435 1700 433 1700 433 C 1700 433 1818 438 1860 494 C 1902 551 1916 584 1922 612 C 1928 640 2 576 2 576 Z"
}
],
duration: 1200,
loop: false,
easing: "easeInOutQuint"
});
svg{
display:inline-block;
width:20em;
overflow:visible;
}
.morph{
transition:0.5s;
}
.morphPoly{
transition:0.5s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<svg id="morph" viewBox="0 0 1920 540">
<path class="morph" d="M 35 576 C 35 576 31 146 377 66 C 722 -14 650 241 864 136 C 901 178 901 178 901 178 C 901 178 781 307 1079 373 C 1377 440 1301 286 1301 286 C 1334 251 1334 251 1334 251 C 1334 251 1359 353 1541 286 C 1723 220 1981 436 1952 667 C 1923 897 35 576 35 576 Z" />
</svg>
...相當多的作業。
但是一旦你的路徑超級兼容,你也可以通過普通的 css 在形狀之間變形。(例如通過影片/過渡d:path()屬性)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/482082.html
上一篇:SVG線/路徑的邊緣/角顏色問題
