簡體   English   中英

如何從Polygon動態更新SVG viewBox值

[英]How can I dynamically update SVG viewBox values from Polygon

我創建了漫畫書頁面板的SVG地圖。

<svg id="svg1413"  class="svg-pg" width="100%" height="100%" version="1.1" viewBox="0 0 178 254" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="transition: .6s ease-out;">
    <image id="image1966" width="178" height="254" clip-path="url('#SvgjsClipPath1413')" xlink:href="https://i.imgur.com/yiZFUK4.jpg" />
    <g id="SvgjsG1413" clip-path="url('#SvgjsClipPath1413')" class="click-panels">
        <polygon fill="transparent" points=" 12,13 88,13 88,49 12,49"></polygon>
        <polygon fill="transparent" points=" 81,44 166,44 166,74 81,74"></polygon>
        <polygon fill="transparent" points=" 12,13 166,13 166,75 12,75"></polygon>
        <polygon fill="transparent" points=" 101,80 166,80 166,118 101,118"></polygon>
        <polygon fill="transparent" points=" 12,80 166,80 166,147 12,147"></polygon>
        <polygon fill="transparent" points=" 12,152 91,152 91,200 12,200"></polygon>
        <polygon fill="transparent" points=" 73,171 155,171 155,209 73,209"></polygon>
        <polygon fill="transparent" points=" 12,198 79,198 79,235 12,235"></polygon>
        <polygon fill="transparent" points=" 12,152 166,152 166,235 12,235"></polygon>
    </g>
    <defs id="SvgjsDefs1413">
        <clipPath id="SvgjsClipPath1413">
            <rect id="SvgjsRect1413" width="100%" height="100%" x="0" y="0">
            </rect>
        </clipPath>
    </defs>     
</svg>
<svg>
    ...svg content
</svg>
<svg>
    ...svg content
</svg>

我想要實現的是:

  • 遍歷所有<svg>標簽
  • 在<svg>上,循環遍歷<svg>中包含的<polygon>標簽
  • 每個<polygon>包含4對坐標(例如, points=" x1,y1 x2,y2 x3,y3 x4,y4"
  • 我希望使用循環中當前<polygon>點的值更新父<svg> viewBox值和<rect> X和Y值。

我已經弄清楚如何計算值,但我不知道如何在Javascript中實現這一點。

我的偽代碼用於計算<svg> viewBox

if <svg viewBox=" a b c d ">
a = x1, b = y1, c = x2 - x1, d = y3 - y2

更新<rect>值

if <rect x="e" y="f">
e = x1, f = y1

更新:如何通過點擊/滑動事件控制過渡而不是自動?

<div id="controls" class="ctl-btn" style="width: 100%; position: absolute; bottom: 0; margin: 0 -8px; background-color: rgba(6,6,6,0.40);">
    <div style="max-width: 800px; text-align: center; margin: 0 auto;">
        <button class="pg-ctl-bk" style="margin: 8px; padding: 8px 10px;">  Back </button>
        <button class="pg-ctl-nxt" style="margin: 8px; padding: 8px 10px;"> Next  </button>
    </div>
</div>

我不知道為什么你在這里使用<polygon>元素,當你需要的只是一個javascript數組/ JSON,或者最終的<rect>元素,它們至少具有viewBox屬性所要求的xywidthheight屬性,但是很好...讓我們處理<polygon> s然后......

要將<polygon>的point屬性值轉換為viewBox屬性,最簡單的方法是調用polygonElement.getBBox() ,它將返回帶有所需值的SVGRect。

要使viewBox屬性設置動畫,最簡單的可能是使用SMIL動畫,以及MS瀏覽器的polyfill。

您只需定義一個定位viewBox屬性的<animate>元素,並在將其from屬性更新為當前值后將其to屬性更新為目標值。

// animate : <animate attributeName="viewBox" ...>
// rect : {SVGRect} result of polygonElement.getBBox();
function animateViewBox(animate, rect) {
  animate.setAttribute('from', animate.getAttribute('to'));
  animate.setAttribute('to', `${rect.x} ${rect.y} ${rect.width} ${rect.height}`);
  animate.beginElement(); // (re)start the animation
}

一旦我們有了這個,我們只需要設置一個函數來迭代svg中的所有<polygon>元素。

 function animateViewBox(animate, rect) { animate.setAttribute('from', animate.getAttribute('to')); animate.setAttribute('to', `${rect.x} ${rect.y} ${rect.width} ${rect.height}`); animate.beginElement(); // (re)start the animation } // container const svg = document.getElementById('svg1413'); // all the <polygons> coordinates (would be better as JSON...) const polygons = svg.querySelectorAll('polygon'); // <animate> element const animator = svg.querySelector('.viewBoxAnimator'); // our iterator, we could call it on click let i = 0; function iterate() { if (i < polygons.length) { animateViewBox(animator, polygons[i++].getBBox()); return true; } } // but we'll automate it (async() => { while (iterate()) { await wait(1500); } })(); function wait(time) { return new Promise(res => setTimeout(res, time)); } 
 svg { width: 100%; height: 100%; max-width: 100vw; max-height: 100vh; transition: all .6s; } html { background: black; } 
 <!-- SMIL for IE --> <script src="https://cdn.jsdelivr.net/gh/Kaiido/FakeSmile@1e50d675df616a8e784e0e6e931b3f0d595367d4/smil.user.js"></script> <svg id="svg1413" class="svg-pg" width="154" height="83" version="1.1" viewBox="0 0 178 254" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <animate class="viewBoxAnimator" attributeType="XML" attributeName="viewBox" from="0 0 178 254" to="0 0 178 254" dur="0.6s" fill="freeze"/> <image id="image1966" width="178" height="254" xlink:href="https://i.imgur.com/yiZFUK4.jpg" /> <g id="SvgjsG1413" class="click-panels"> <polygon fill="transparent" points=" 12,13 88,13 88,49 12,49"></polygon> <polygon fill="transparent" points=" 81,44 166,44 166,74 81,74"></polygon> <polygon fill="transparent" points=" 12,13 166,13 166,75 12,75"></polygon> <polygon fill="transparent" points=" 101,80 166,80 166,118 101,118"></polygon> <polygon fill="transparent" points=" 12,80 166,80 166,147 12,147"></polygon> <polygon fill="transparent" points=" 12,152 91,152 91,200 12,200"></polygon> <polygon fill="transparent" points=" 73,171 155,171 155,209 73,209"></polygon> <polygon fill="transparent" points=" 12,198 79,198 79,235 12,235"></polygon> <polygon fill="transparent" points=" 12,152 166,152 166,235 12,235"></polygon> </g> </svg> 

你使用了svg.js標簽,所以你得到一個svg.js答案:

 // Reference to svg const canvas = SVG('#svg1413') // List of all polygons const polygons = canvas.find('#SvgjsG1413 polygon') // List of all bboxes const boxes = polygons.bbox() const nextImage = function (index) { // Animate viewbox over 1s to new box canvas.animate(1000).viewbox(boxes[index]) // Next image in 2s setTimeout(() => nextImage(++index), 2000) } nextImage(0) 
 svg { width: 100%; height: 100%; max-width: 100vw; max-height: 100vh; } html { background: black; } 
 <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@latest/dist/svg.min.js"></script> <svg id="svg1413" class="svg-pg" width="154" height="254" version="1.1" viewBox="0 0 178 254" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="transition: .6s ease-out;"> <image id="image1966" width="178" height="254" clip-path="url('#SvgjsClipPath1413')" xlink:href="https://i.imgur.com/yiZFUK4.jpg" /> <g id="SvgjsG1413" clip-path="url('#SvgjsClipPath1413')" class="click-panels"> <polygon fill="transparent" points=" 12,13 88,13 88,49 12,49"></polygon> <polygon fill="transparent" points=" 81,44 166,44 166,74 81,74"></polygon> <polygon fill="transparent" points=" 12,13 166,13 166,75 12,75"></polygon> <polygon fill="transparent" points=" 101,80 166,80 166,118 101,118"></polygon> <polygon fill="transparent" points=" 12,80 166,80 166,147 12,147"></polygon> <polygon fill="transparent" points=" 12,152 91,152 91,200 12,200"></polygon> <polygon fill="transparent" points=" 73,171 155,171 155,209 73,209"></polygon> <polygon fill="transparent" points=" 12,198 79,198 79,235 12,235"></polygon> <polygon fill="transparent" points=" 12,152 166,152 166,235 12,235"></polygon> </g> </svg> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM