vue-SVG图形

作者: 孤独花园 | 来源:发表于2016-08-22 16:46 被阅读4565次
    SVG图形
    传送门
    此实例主要涉及vue的组件,computed等知识。
    上js代码:
    // The raw data to observe
    var stats = [ // 定义初始的数据
      { label: 'A', value: 100 },
      { label: 'B', value: 100 },
      { label: 'C', value: 100 },
      { label: 'D', value: 100 },
      { label: 'E', value: 100 },
      { label: 'F', value: 100 }
    ]
    
    // A resusable polygon graph component
    Vue.component('polygraph', { // 定义并注册一个图形组件
      props: ['stats'], // 传递父组件传递来的数据
      template: '#polygraph-template',  
      replace: true,
      computed: {
        // 实时响应图形中的point,通过改变stat的value,来改变图形
        points: function () {
          var total = this.stats.length
          return this.stats.map(function (stat, i) { // 遍历stats中的每个值,计算出各个点的位置
            var point = valueToPoint(stat.value, i, total)
            return point.x + ',' + point.y
          }).join(' ')
        }
      },
      components: {
        // 一个子组件,可调整stats中value的值
        'axis-label': {
          props: {
            stat: Object,
            index: Number,
            total: Number
          },
          template: '#axis-label-template',
          replace: true,
          computed: {
            point: function () {
              return valueToPoint(
                +this.stat.value + 10,
                this.index,
                this.total
              )
            }
          }
        }
      }
    })
    
    // 通过数学方法来画图
    function valueToPoint (value, index, total) {
      var x     = 0
      var y     = -value * 0.8
      var angle = Math.PI * 2 / total * index
      var cos   = Math.cos(angle)
      var sin   = Math.sin(angle)
      var tx    = x * cos - y * sin + 100
      var ty    = x * sin + y * cos + 100
      return {
        x: tx,
        y: ty
      }
    }
    
    // 创建根实例
    new Vue({
      el: '#demo',
      data: {
        newLabel: '',
        stats: stats
      },
      methods: {
        add: function (e) {
          e.preventDefault() // 取消事件的默认动作
          if (!this.newLabel) return
          this.stats.push({
            label: this.newLabel,
            value: 100
          })
          this.newLabel = ''
        },
        remove: function (stat) {
          if (this.stats.length > 3) {
            this.stats.$remove(stat) // $remove 是vue添加的方法,从目标数组中查找并删除元素,在内部它调用 splice()
          } else {
            alert('Can\'t delete more!')
          }
        }
      }
    })
    
    再来看看我们的html代码:
    <!-- polygraph组件的template,其中包含子组件的调用 -->
    <script type="text/x-template" id="polygraph-template">
      <g>
        <polygon :points="points"></polygon>
        <circle cx="100" cy="100" r="80"></circle>
        <axis-label
          v-for="stat in stats"
          :stat="stat"
          :index="$index"
          :total="stats.length">
        </axis-label>
      </g>
    </script>
    
    <!-- axis label组件的template,用于调整数值来改变图像 -->
    <script type="text/x-template" id="axis-label-template">
      <text :x="point.x" :y="point.y">{{stat.label}}</text>
    </script>
    
    <!-- 根实例 -->
    <div id="demo">
      <!-- 在这使用polygraph组件 -->
      <svg width="200" height="200">
        <polygraph :stats="stats"></polygraph>
      </svg>
      <!-- 可控制数值大小,并添加删除元素 -->
      <div v-for="stat in stats">
        <label>{{stat.label}}</label>
        <input type="range" v-model="stat.value" min="0" max="100">
        <span>{{stat.value}}</span>
        <button @click="remove(stat)">X</button>
      </div>
      <form id="add">
        <input name="newlabel" v-model="newLabel">
        <button @click="add">Add a Stat</button>
      </form>
      <pre id="raw">{{stats | json}}</pre>
    </div>
      
    <p style="font-size:12px">* input[type="range"] requires IE10 or above.</p>
    
    最后是css代码:
    body {
        font-family: Helvetica Neue, Arial, sans-serif;
    }
    
    polygon {
        fill: #42b983;
        opacity: .75;
    }
    
    circle {
        fill: transparent;
        stroke: #999;
    }
    
    text {
        font-family: Helvetica Neue, Arial, sans-serif;
        font-size: 10px;
        fill: #666;
    }
    
    label {
        display: inline-block;
        margin-left: 10px;
        width: 20px;
    }
    
    #raw {
        position: absolute;
        top: 0;
        left: 300px;
    }
    
    写到最后你会感受到编程的神奇,vue的便捷。

    相关文章

      网友评论

        本文标题:vue-SVG图形

        本文链接:https://www.haomeiwen.com/subject/yfhgsttx.html