zoukankan      html  css  js  c++  java
  • 三种图表技术SVG、Canvas、WebGL 3D比较

    1.什么是SVG?

    描述:

    • 一种使用XML描述的2D图形的语言
    • SVG基于XML意味着,SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。
    • 在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

    2.什么是canvas?

    描述:

    • 通过Javascript来绘制2D图形。
    • 是逐像素进行渲染的。
    • 其位置发生改变,会重新进行绘制。

    3.什么是WebGL 3D?

    • 说白了就是基于Canvas的3D框架
    • 主要用来做 3D 展示、动画、游戏。

    因为前两项都是描述2D图形的,而WebGL是描述3d的,所以以下针对SVG和Canvas做比较。

    3.有了Canvas为什么还要使用SVG

    最重要的一点是SVG不依赖于终端设备的像素,可以随意放大缩小但是不会失真

    继续:为什么SVG放大不会失真而Canvas却会变模糊呢?

    因为SVG的渲染的原理是通过对图形的数学描述来绘图的,例如:以下哆啦A梦的头型的思路是,我先画一个贝塞尔函数,然后填充颜色。

    而Canvas的渲染原理是通过对每个像素颜色的填充,最后组成图形,例如:以下马里奥的帽子我们可以看出,其实帽子的形状是由一个个像素填充出来的。

    另外Canvas渲染出来的图叫位图,SVG渲染出来的图叫矢量图

    看到这里你肯定会觉得那直接所有图形都用SVG画不就行了,位图就可以直接淘汰了呀,但是SVG画的图也有缺点,以下针对两者的不同做一个对比。

    4.两者的对比

    理解适用场景:

    从以下这张微软开发社区公布的性能图中也可以看出,SVG在绘图面积较大,数据量较小的时候性能较好,渲染时间较短,而Canvas刚好相反。

    5.总结

    Canvas和SVG两者的适用场景不同,开发者在使用是应根据具体的项目需求来选择相应的渲染方式。

    最后附上一个SVG编译器帮大家更好的理解和使用SVG

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>SVG 编辑器</title>
        <style>
            #toolbox {
                position: absolute;
                top: 0;
                bottom: 0;
                left: 0;
                 250px;
                border-right: 1px solid #CCC;
            }
    
            #toolbox h2 {
                margin: 0;
                padding: 0;
                background: #EEE;
                font-size: 16px;
                height: 24px;
                line-height: 24px;
                padding: 5px 10px;
            }
    
            #toolbox form {
                padding: 10px;
            }
    
            #canvas {
                position: absolute;
                left: 260px;
                top: 10px;
                bottom: 10px;
                right: 10px;
                box-shadow: 2px 2px 10px rgba(0,0,0,.4);
                border-radius: 5px;
            }
    
            label {
                display: inline-block;
                 80px;
                text-align: right;
            }
        </style>
    </head>
    <body>
        <div id="toolbox">
            <h2>创建</h2>
            <form id="create-shape">
                <button type="button" create="rect">Rect</button>
                <button type="button" create="circle">Circle</button>
                <button type="button" create="ellipse">Ellipse</button>
                <button type="button" create="line">Line</button>
            </form>
            <h2>形状</h2>
            <form id="shape-attrs">
                请先创建图形
            </form>
            <h2>外观和变换</h2>
            <form id="look-and-transform" disabled="disabled">
                <p>
                    <label style="display: inline;">填充</label>
                    <input id="fill" type="color" value="#ffffff" />
                </p>
                <p>
                    <label style="display: inline;">描边</label>
                    <input id="stroke" type="color" value="#ff0000" />
                    <input id="strokeWidth" type="range" value="1" />
                </p>
                <p>
                    <label>translateX</label>
                    <input id="translateX" type="range" min="-400" max="400" value="0" />
    
                    <label>translateY</label>
                    <input id="translateY" type="range" min="-400" max="400" value="0" />
    
                    <label>rotate</label>
                    <input id="rotate" type="range" min="-180" max="180" value="0" />
    
                    <label>scale</label>
                    <input id="scale" type="range" min="-1" max="2" step="0.01" value="1" />
                </p>
            </form>
        </div>
        <div id="canvas"></div>
    </body>
    <script>
        var SVG_NS = 'http://www.w3.org/2000/svg';
    
        // 图形及对应默认属性
        var shapeInfo = {
            rect: 'x:10,y:10,200,height:100,rx:0,ry:0',
            circle: 'cx:200,cy:200,r:50',
            ellipse: 'cx:200,cy:200,rx:80,ry:30',
            line: 'x1:10,y1:10,x2:100,y2:100'
        };
    
        // 默认公共属性
        var defaultAttrs = {
            fill: '#ffffff',
            stroke: '#ff0000'
        };
    
        var createForm = document.getElementById('create-shape');
        var attrForm = document.getElementById('shape-attrs');
        var lookForm = document.getElementById('look-and-transform');
    
        var svg = createSVG();
        var selected = null;
    
        createForm.addEventListener('click', function(e) {
            if (e.target.tagName.toLowerCase() == 'button') {
                create(e.target.getAttribute('create'));
            }
        });
    
        attrForm.addEventListener('input', function(e) {
            if (e.target.tagName.toLowerCase() != 'input') return;
            var handle = e.target;
            selected.setAttribute(handle.name, handle.value);
        });
    
        lookForm.addEventListener('input', function(e) {
            if (e.target.tagName.toLowerCase() != 'input') return;
            if (!selected) return;
            selected.setAttribute('fill', fill.value);
            selected.setAttribute('stroke', stroke.value);
            selected.setAttribute('stroke-width', strokeWidth.value);
            selected.setAttribute('transform', encodeTranform({
                tx: translateX.value,
                ty: translateY.value,
                scale: scale.value,
                rotate: rotate.value
            }));
        });
    
        function createSVG() {
            var svg = document.createElementNS(SVG_NS, 'svg');
            svg.setAttribute('width', '100%');
            svg.setAttribute('height', '100%');
            canvas.appendChild(svg);
    
            svg.addEventListener('click', function(e) {
                if (e.target.tagName.toLowerCase() in shapeInfo) {
                    select(e.target);
                }
            });
            return svg;
        }
    
        function create(name) {
            var shape = document.createElementNS(SVG_NS, name);
            svg.appendChild(shape);
            select(shape);
        }
    
        function select(shape) {
            var attrs = shapeInfo[shape.tagName].split(',');
            var attr, name, value;
    
            attrForm.innerHTML = "";
    
            while(attrs.length) {
                attr = attrs.shift().split(':');
                name = attr[0];
                value = shape.getAttribute(name) || attr[1];
                createHandle(shape, name, value);
                shape.setAttribute(name, value);
            }
    
            for (name in defaultAttrs) {
                value = shape.getAttribute(name) || defaultAttrs[name];
                shape.setAttribute(name, value);
            }
            selected = shape;
    
            updateLookHandle();
        }
    
        function createHandle(shape, name, value) {
            
    
            var label = document.createElement('label');
            label.textContent = name;
    
            var handle = document.createElement('input');
            handle.setAttribute('name', name);
            handle.setAttribute('type', 'range');
            handle.setAttribute('value', value);
            handle.setAttribute('min', 0);
            handle.setAttribute('max', 800);
    
            attrForm.appendChild(label);
            attrForm.appendChild(handle);
        }
    
        function updateLookHandle() {
            fill.value = selected.getAttribute('fill');
            stroke.value = selected.getAttribute('stroke');
            var t = decodeTransform(selected.getAttribute('transform'));
            translateX.value = t ? t.tx : 0;
            translateY.value = t ? t.ty : 0;
            rotate.value = t ? t.rotate : 0;
            scale.value = t ? t.scale : 1;
        }
    
        function decodeTransform(transString) {
            var match = /translate((d+),(d+))srotate((d+))sscale((d+))/.exec(transString);
            return match ? {
                tx: +match[1],
                ty: +match[2],
                rotate: +match[3],
                scale: +match[4]
            } : null;
        }
    
        function encodeTranform(transObject) {
            return ['translate(', transObject.tx, ',', transObject.ty, ') ',
                'rotate(', transObject.rotate, ') ',
                'scale(', transObject.scale, ')'].join('');
        }
    
    </script>
    </html>
    View Code
  • 相关阅读:
    筛选法 || POJ 1356 Prime Land
    搜索 || BFS || POJ 3278 Catch That Cow
    (素数筛) 找质数
    (map)后缀字符串
    字符串的进制
    (二进制枚举子集)买玩具
    (基础)01背包问题
    (基础)编辑距离
    (基础)最长公共字串
    最大子矩阵和
  • 原文地址:https://www.cnblogs.com/liutianzeng/p/11322009.html
Copyright © 2011-2022 走看看