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