# 指南

# 基本示例

初始化画布,并添加图形

点击查看代码
<template>
  <div class="demo1"></div>
</template>

<script>
import GRender, { Rect, Line, Arrow, Circle, Ellipse } from 'grender'

export default {
  name: 'Demo1',
  mounted() {
    this.grender = new GRender(this.$el)
    const x = this.$el.offsetWidth / 2 - 30
    const rect = new Rect({
      shape: {
        x,
        y: 40,
        width: 80,
        height: 40
      }
    })

    const line = new Line({
      shape: {
        x1: x - 50,
        y1: 40,
        x2: x + 50,
        y2: 160
      }
    })

    const arrow = new Arrow({
      shape: {
        x1: x - 30,
        y1: 40,
        x2: x + 10,
        y2: 160
      }
    })

    const circle = new Circle({
      shape: {
        x,
        y: 100,
        r: 40
      }
    })

    const ellipse = new Ellipse({
      shape: {
        x: x + 60,
        y: 120,
        rx: 60,
        ry: 30
      }
    })

    this.grender.add(rect)
    this.grender.add(line)
    this.grender.add(arrow)
    this.grender.add(circle)
    this.grender.add(ellipse)
    window.addEventListener('resize', this.resize)
  },
  destroyed() {
    window.removeEventListener('resize', this.resize)
    this.grender.destroy()
  },
  methods: {
    resize() {
      this.grender.resize()
    }
  }
}
</script>

<style lang="stylus">
.demo1
  height 180px
</style>

# 图形样式

默认情况下,图形添加到画布中后会有默认样式,我们可以在初始化时设置图形的样式

TIP

图形在画布中的层级关系,默认是添加到画布中的顺序,后添加的层级更高,我们也可以在初始化化时指定z值,从而调整某个图形的层级。 上图中我们手动指定了矩形的层级为1,所以它会被绘制到最上层。图形默认z值为0

点击查看代码
<template>
  <div class="demo2"></div>
</template>

<script>
import GRender, { Rect, Circle, Ellipse } from 'grender'

export default {
  name: 'Demo2',
  mounted() {
    this.grender = new GRender(this.$el)
    const x = this.$el.offsetWidth / 2 - 30
    const rect = new Rect({
      brush: {
        fillStyle: 'green',
        strokeStyle: 'green',
        globalAlpha: 0.9
      },
      shape: {
        x,
        y: 40,
        width: 80,
        height: 40
      },
      z: 1
    })

    const circle = new Circle({
      brush: {
        lineWidth: 4,
        strokeStyle: 'blue'
      },
      shape: {
        x,
        y: 100,
        r: 40
      }
    })

    const ellipse = new Ellipse({
      brush: {
        lineWidth: 0,
        fillStyle: 'red',
        globalAlpha: 0.9
      },
      shape: {
        x: x + 60,
        y: 120,
        rx: 60,
        ry: 30
      }
    })

    this.grender.add(rect)
    this.grender.add(circle)
    this.grender.add(ellipse)
    window.addEventListener('resize', this.resize)
  },
  destroyed() {
    window.removeEventListener('resize', this.resize)
    this.grender.destroy()
  },
  methods: {
    resize() {
      this.grender.resize()
    }
  }
}
</script>

<style lang="stylus">
.demo2
  height 180px
</style>

# 图形变换

图形目前支持translate(移动)scale(缩放)rotate(旋转)三种变换

矩形变换
椭圆变换

TIP

图形变换(rotate、scale)的中心点默认为图形为所在局部坐标的原点(0,0),我们也可以通过origin参数指定变换中心

点击查看代码
<template>
  <div class="demo3">
    <h5>矩形变换</h5>
    <button @click="translateX(rect)">x + 10</button>
    <button @click="translateY(rect)">y + 10</button>
    <button @click="rotate(rect)">旋转30°</button>
    <button @click="scale(rect, 1.2)">放大1.2倍</button>
    <button @click="scale(rect, 1 / 1.2)">缩小1.2倍</button>
    <div class="demo3-canvas" ref="rect"></div>
    <h5>椭圆变换</h5>
    <button @click="translateX(ellipse)">x + 10</button>
    <button @click="translateY(ellipse)">y + 10</button>
    <button @click="rotate(ellipse)">旋转30°</button>
    <button @click="scale(ellipse, 1.2)">放大1.2倍</button>
    <button @click="scale(ellipse, 1 / 1.2)">缩小1.2倍</button>
    <div class="demo3-canvas" ref="ellipse"></div>
  </div>
</template>

<script>
import GRender, { Rect, Ellipse } from 'grender'

export default {
  name: 'Demo3',
  mounted() {
    this.grender1 = new GRender(this.$refs.rect)
    this.rect = new Rect({
      origin: [40, 20],
      brush: {
        fillStyle: 'red',
        strokeStyle: 'red'
      },
      shape: {
        x: 0,
        y: 0,
        width: 80,
        height: 40
      }
    })

    this.grender1.add(this.rect)

    this.grender2 = new GRender(this.$refs.ellipse)

    this.ellipse = new Ellipse({
      origin: [100, 100],
      brush: {
        fillStyle: 'red',
        strokeStyle: 'red'
      },
      shape: {
        x: 100,
        y: 100,
        rx: 60,
        ry: 30
      }
    })
    this.grender2.add(this.ellipse)
    window.addEventListener('resize', this.resize)
  },
  destroyed() {
    window.removeEventListener('resize', this.resize)
    this.grender1.destroy()
    this.grender2.destroy()
  },
  methods: {
    resize() {
      this.grender1.resize()
      this.grender2.resize()
    },
    translateX(shape) {
      const [x, y] = shape.T
      shape.translate(x + 10, y)
    },
    translateY(shape) {
      const [x, y] = shape.T
      shape.translate(x, y + 10)
    },
    rotate(shape) {
      const r = shape.R
      shape.rotate(r + 30)
    },
    scale(shape, val) {
      const [x, y] = shape.S
      shape.scale(x * val, y * val)
    }
  }
}
</script>

<style lang="stylus">
.demo3-canvas
  height 300px
</style>

# 鼠标事件

图形目前支持clickdblclickwheelmousedownmousemovemouseupmouseovermouseoutmouseenter和与mouseleave事件。同时也支持dragstartdraggingdragend等复合事件

当前触发事件:
点击查看代码
<template>
  <div class="demo4">
    <div>当前触发事件:{{ event }}</div>
    <div class="demo4-canvas" ref="canvas"></div>
  </div>
</template>

<script>
import GRender, { Rect, Line, Arrow, Circle, Ellipse } from 'grender'

export default {
  name: 'Demo4',
  data () {
    return {
      event: undefined
    }
  },
  mounted () {
    this.grender = new GRender(this.$refs.canvas)
    const x = this.$refs.canvas.offsetWidth / 2 - 30
    const rect = new Rect({
      shape: {
        x,
        y: 40,
        width: 80,
        height: 40
      }
    })

    const line = new Line({
      brush: {
        lineWidth: 2
      },
      shape: {
        x1: x - 50,
        y1: 40,
        x2: x + 50,
        y2: 160
      }
    })

    const arrow = new Arrow({
      brush: {
        lineWidth: 10
      },
      shape: {
        x1: x - 30,
        y1: 40,
        x2: x - 40,
        y2: 160
      }
    })

    const circle = new Circle({
      shape: {
        x,
        y: 100,
        r: 40
      }
    })

    const ellipse = new Ellipse({
      shape: {
        x: x + 60,
        y: 120,
        rx: 60,
        ry: 30
      }
    })

    this.grender.add(rect)
    this.grender.add(line)
    this.grender.add(arrow)
    this.grender.add(circle)
    this.grender.add(ellipse)

    this.grender.shapes.forEach(shape => {
      shape.on('dragging', e => {
        shape.translate(e.x, e.y)
        this.event = 'dragging'
      })

      shape.on('mouseenter', e => {
        shape.brush.fillStyle = 'red'
        shape.brush.strokeStyle = 'blue'
        this.event = 'mouseenter'
        this.$refs.canvas.style.cursor = 'pointer'
        this.grender.refresh()
      })
      shape.on('mouseleave', e => {
        shape.brush.fillStyle = 'rgba(0,0,0,0)'
        shape.brush.strokeStyle = '#000'
        this.event = 'mouseleave'
        this.$refs.canvas.style.cursor = 'default'
        this.grender.refresh()
      })
    })
    window.addEventListener('resize', this.resize)
  },
  destroyed () {
    window.removeEventListener('resize', this.resize)
    this.grender.destroy()
  },
  methods: {
    resize () {
      this.grender.resize()
    }
  }
}
</script>

<style lang="stylus">
.demo4
  border 2px solid #000
  &-canvas
    height 240px
</style>