zoukankan      html  css  js  c++  java
  • 可视化svg深入理解viewport、viewbox、preserveaspectradio

    直接运行此例子

    深入理解svg的viewport、viewbox、preserveaspectradio实例

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="author" content="李可">
        <title>svgviewBox的特写过程。演示动画</title>
        <style>
            div {
                box-sizing: border-box;
            }
    
            span {
                font-weight: bolder;
            }
        </style>
    </head>
    
    <body>
        <fieldset style="800px;">
            <legend>
                <h2>viewport,viewBox,preserveAspectRatio演示-李可</h2>
            </legend>
            <h4>viewport: </h4>
            <label for="viewportWidthNumber"></label>
            <input type="number" id='viewportWidthNumber' value="400" oninput="updateView('#svg','width',this.value)" />
            <label for="viewportHeightNumber">height:</label>
            <input type="number" id='viewportHeightNumber' value="300" oninput="updateView('#svg','height',this.value)" />
            <h4>viewBox: </h4>
            <label for="viewBoxWidthNumber"></label>
            <input type="number" id='viewBoxWidthNumber' value="40" oninput="updateView('#react','width',this.value)" />
            <label for="viewBoxHeightNumber">height:</label>
            <input type="number" id='viewBoxHeightNumber' value="30" oninput="updateView('#react','height',this.value)" />
            <h4>preserveAspectRatio(align,meetOrSlice)</h4>
            <select name="align" id="align" onchange="preserveAspectRadioFirst(this.value)">
                    <option value="none">none</option>
                    <option value="xMinYMin">xMinYMin</option>
                    <option value="xMinYMid">xMinYMid</option>
                    <option value="xMinYMax">xMinYMax</option>
                    <option value="xMidYMin">xMidYMin</option>
                    <option value="xMidYMid" selected>xMidYMid</option>
                    <option value="xMidYMax">xMidYMax</option>
                    <option value="xMaxYMin">xMaxYMin</option>
                    <option value="xMaxYMid">xMaxYMid</option>
                    <option value="xMaxYMax">xMaxYMax</option>
            </select>
            <select name="meetOrSlice" id="meetOrSlice">
                    <option value="meet" selected>meet</option>
                    <option value="slice">slice</option>
            </select>
            <p>viewBox,默认 0 0 width height</p>
            <p>preserverAspectRadio,默认xMidYMid meet,如果align是none,meetOrSlice的值将会被忽略</p>
            <div id="note" style="visibility:hidden;">
                <p>按照---><span id="direction"></span>,缩放 ---> <span id="percent"></span>倍</p>
            </div>
            <button type="button" id="btn">运动动画</button>
        </fieldset>
        <div id="svg" style="margin:100px 0 0 100px;position:relative;400px;height:300px; background:gray;">vport
            <div id="react" style="position:absolute;40px;height:30px;background:green;">vBox
                <div id="realDiv" style="position:absolute;top:0;left:0;opacity:0.5;margin:10% 0 0 15%;30%;height:50%;background:red;"></div>
            </div>
        </div>
        <script>
            let updateView = (selector, attr, val) => {
                document.querySelector(selector).style[attr] = val + 'px';
                preserveAspectRadioFirst(align.value)
            }
    
            let preserveAspectRadioFirst = (startPosition = 'xMidYMid') => {
                const svgW = viewportWidthNumber.value;
                const svgH = viewportHeightNumber.value;
                const reactW = viewBoxWidthNumber.value;
                const reactH = viewBoxHeightNumber.value;
                switch (align.value) {
                    case 'none':
                        react.style.transformOrigin = 'center center';
                        react.style.left = (svgW - reactW) / 2 + 'px';
                        react.style.top = (svgH - reactH) / 2 + 'px';
                        break;
                    case 'xMinYMin':
                        react.style.transformOrigin = 'left top';
                        react.style.left = 0 + 'px';
                        react.style.top = 0 + 'px';
                        break;
                    case 'xMinYMid':
                        react.style.transformOrigin = 'left center';
                        react.style.left = 0 + 'px';
                        react.style.top = (svgH - reactH) / 2 + 'px';
                        break;
                    case 'xMinYMax':
                        react.style.transformOrigin = 'left bottom';
                        react.style.left = 0 + 'px';
                        react.style.top = (svgH - reactH) + 'px';
                        break;
                    case 'xMidYMin':
                        react.style.transformOrigin = 'center center';
                        react.style.left = (svgW - reactW) / 2 + 'px';
                        react.style.top = 0 + 'px';
                        break;
                    case 'xMidYMid':
                        react.style.transformOrigin = 'center center';
                        react.style.left = (svgW - reactW) / 2 + 'px';
                        react.style.top = (svgH - reactH) / 2 + 'px';
                        break;
                    case 'xMidYMax':
                        react.style.transformOrigin = 'center bottom';
                        react.style.left = (svgW - reactW) / 2 + 'px';
                        react.style.top = (svgH - reactH) + 'px';
                        break;
                    case 'xMaxYMin':
                        react.style.transformOrigin = 'right top';
                        react.style.left = (svgW - reactW) + 'px';
                        react.style.top = 0 + 'px';
                        break;
                    case 'xMaxYMid':
                        react.style.transformOrigin = 'right center';
                        react.style.left = (svgW - reactW) + 'px';
                        react.style.top = (svgH - reactH) / 2 + 'px';
                        break;
                    case 'xMaxYMax':
                        react.style.transformOrigin = 'right bottom';
                        react.style.left = (svgW - reactW) + 'px';
                        react.style.top = (svgH - reactH) + 'px';
                        break;
                }
            }
            preserveAspectRadioFirst(align.value);
    
            let awaitFn = () => {
                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        react.style.transitionDuration = '0s';
                        resolve()
                    })
                })
            }
            let inputs = document.querySelectorAll('input');
            let selects = document.querySelectorAll('select');
    
            let disableEle = () => {
                for (let i = 0; i < inputs.length; i++) {
                    inputs[i].setAttribute('disabled', 'disabled')
                }
                for (let i = 0; i < selects.length; i++) {
                    selects[i].setAttribute('disabled', 'disabled')
                }
            }
            let enbledEle = () => {
                for (let i = 0; i < inputs.length; i++) {
                    inputs[i].removeAttribute('disabled')
                }
                for (let i = 0; i < selects.length; i++) {
                    selects[i].removeAttribute('disabled')
                }
            }
    
            let step = 1;
            btn.addEventListener('click', async e => {
                if (step % 2) {
                    btn.innerHTML = '初始化'
                    disableEle();
                    react.style.transition = "transform 5s";
    
                    const svgW = viewportWidthNumber.value;
                    const svgH = viewportHeightNumber.value;
                    const reactW = viewBoxWidthNumber.value;
                    const reactH = viewBoxHeightNumber.value;
                    svg.style.width = svgW + 'px';
                    svg.style.height = svgH + 'px';
                    react.style.width = reactW + 'px';
                    react.style.height = reactH + 'px';
    
                    let p = (reactW / reactH) / (svgW / svgH) > 1;//p>1,viewbox宽先到viewport的宽 p<1,viewbox高先到viewport的高
                    let s = meetOrSlice.value;
                    let scaleX = svgW / reactW;
                    let scaleY = svgH / reactH;
                    let scale = p ?
                        s == 'meet' ? scaleX : scaleY :
                        s == 'meet' ? scaleY : scaleX;
    
                    //note
                    let derector = p ?
                        s == 'meet' ? 'x轴' : 'y轴' :
                        s == 'meet' ? 'y轴' : 'x轴';
                    percent.innerHTML = scale;
                    direction.innerHTML = derector;
                    note.style.visibility = 'visible';
                    //note
    
                    react.style.transform = "scale(" + scale + ")";
                } else {
                    note.style.visibility = 'hidden';
                    enbledEle()
                    await awaitFn()
                    react.style.transform = 'scale(1)'
                    react.style.background = 'green'
                    btn.innerHTML = '运动动画'
                }
                step++;
            })
    
            react.addEventListener('transitionend', e => {
                if (e.propertyName == 'transform') {
                    react.style.transition = "background 5s";
                    react.style.background = 'transparent';
                }
            });
        </script>
    </body>
    
    </html>
    

    viewport的理解

    例子

    这里的viewport的宽高就是svg标签里面的widthheight属性值。默认单位像素px,这里也就是400px*300px,当然可以用其他单位em rem %等等,前提你用得着~哦。然后svg的viewport就讲完了,简单吧。

    <svg width="400" height="300"  style="border:1px solid red">
        <rect width="40" height="30" fill="green"/>
    </svg>
    

    viewBox

    重点理解,绝对不要放过的地方哦

    例子1

    viewBox="x y width height" 或者viewBox="x ,y,width,height" 带不带 逗号
    x:初始矩形的左上点x坐标
    y:初始矩形左上角y坐标
    初始矩形宽度
    height:初始矩形高度

    我画三个图形,跟我先弄懂这三个

    <svg width="400" height="300"  style="border:1px solid red">
            <rect width="40" height="30" />
    </svg>
    <svg width="400" height="300" viewBox="0 0 40 30"  style="border:1px solid red">
            <rect width="40" height="30" />
    </svg><br/>
    <svg width="400" height="300" viewBox="0 0 80 30"  style="border:1px solid red">
            <rect width="40" height="30" />
    </svg>
    

  • 相关阅读:
    android.animation(6)
    android.animation(5)
    android.animation(4)
    android.animation(3)
    android.animation(2)
    android.animation(1)
    android.view.animation(2)
    php热身2:CRUD with Ajax
    PHP热身
    Android热身:通过网络获取资源并更新UI组件
  • 原文地址:https://www.cnblogs.com/leee/p/9123043.html
Copyright © 2011-2022 走看看