Vue带渐变色拾色器

981 阅读1分钟

在vue项目中,我们一般使用element组件,但是有时候组件不能满足我们的需求,物品们这时候就需要自己写组件,今天给大家分享一个带有渐变色的拾色器 首先我在github找到一款用jq写的拾色器,改造为vue拾色器,下面为改造好的拾色器

他不爱你哈colorpicker.png 1.创建拾色器组件,引入拾色器

<template>
  <div class="xxxxx">
    <div :id="domId" class="mypicker" />
  </div>
</template>

<script>
import ColorPicker from './colorpicker'
import { mapState } from 'vuex'
// import {selectGradient} from ''
export default {
  props: {
    color: {
      default: '#ffffff'
    }
  },
  data() {
    return {
      domId: '',
      oldValue: '',
      mouse: { x: -1, y: -1 },
      glass: false,
      hexColor: ''
    }
  },
  watch: {
    fActO(val, oldval) {
      this.domId = 'dom-' + ((new Date()).getTime() + Math.random()).toString().replace('.', '')
      if (this.color.type == 'linear') {
        var zhuanhuan = this.fActO.fill.colorStops.map((e) => {
          return `${e.color} ${e.per}%`
        })
        var color = `linear-gradient(0.0deg,${zhuanhuan})`
      } else {
        var color = this.color == '' ? '#ffffff' : this.color
      }
      console.log(this.color)
      console.log(color)
      this.$nextTick(() => {
        var self = this
        var colorpicker = new ColorPicker({
          color: color,
          selector: '#' + this.domId,
          showprecolor: true, // 显示预制颜色
          prevcolors: null, // 预制颜色,不设置则默认
          showhistorycolor: false, // 显示历史
          historycolornum: 16, // 历史条数
          format: 'hex', // rgba hex hsla,初始颜色类型
          showPalette: true, // 显示色盘
          show: false, // 初始化显示
          lang: 'cn', // cn 、en
          colorTypeOption: 'single,linear-gradient,radial-gradient',
          canMove: false, // 选择器位置是否可以拖拽
          alwaysShow: false,
          autoConfirm: true,
          onError: function(e) {

          },
          onCancel: function(color) {
            console.log('cancel', color)
          },
          onChange: function(color) {
            self.$emit('active-change', color.color.hex)
            // console.log('change', color)
            if (color.colorType == 'single') {
              self.$emit('active-change', color.color.hex)
            } else if (color.colorType == 'linear-gradient') {
              // self.$emit('active-change', color.color.str)
              self.linear(color)
            } else {
              self.radial(color)
            }
          },
          onConfirm: function(color) {
            console.log('confirm', color)
            self.$emit('active-change', color.color.hex)
            // console.log('change', color)
            if (color.colorType == 'single') {
              self.$emit('active-change', color.color.hex)
            } else if (color.colorType == 'linear-gradient') {
              // self.$emit('active-change', color.color.str)
              self.linear(color)
            } else {
              // self.$emit('active-change', color.color.str)
              self.radial(color)
            }
          },
          openSucker: function(color) {
            self.glass = true
            if (color == 1) {
              var imgcan = document.querySelector('#imgcan')
              imgcan.style.display = 'block'
              var glasscan = document.getElementById('glasscan')
              var glasscanimg = document.getElementById('glasscanimg')
              var glasscanp = document.getElementById('glasscanp')
              var imgContext = document.querySelector('#canvas').getContext('2d')
              var glassContext = glasscan.getContext('2d')
              var img = new Image()
              self.mouse = captureMouse(imgcan)
              img.src = self.fObj.toDataURL({ multiplier: 1, withoutTransform: true })
              img.onload = function() {
                imgContext.drawImage(img, self.fObj.width, self.fObj.height)
              }
              // 获取元素内鼠标位置
              function captureMouse(element) {
                element.addEventListener('mousemove', function(event) {
                  var x = event.pageX
                  var y = event.pageY
                  if (event.type == 'touchstart') {
                    x = event.touches[0].clientX
                    y = event.touches[0].clientY
                  }
                  var canvas = event.target
                  self.mouse = self.getPointOnCanvas(canvas, x, y)
                }, false)
              }
              // 给画布绑定鼠标移动事件
              imgcan.onmousemove = function() {
                glassContext.clearRect(0, 0, glasscan.width, glasscan.height)
                glasscan.style.left = self.mouse.x + 'px'
                glasscan.style.top = self.mouse.y + 'px'
                glasscanimg.style.left = self.mouse.x + 'px'
                glasscanimg.style.top = self.mouse.y + 'px'
                glasscanp.style.left = self.mouse.x + 90 + 'px'
                glasscanp.style.top = self.mouse.y + 180 + 'px'
                // 显示鼠标位置
                // console.log(self.mouse.x, self.mouse.y)
                // console.log(imgContext.getImageData(self.mouse.x, self.mouse.y, 1, 1).data)
                var imageData = imgContext.getImageData(self.mouse.x, self.mouse.y, 1, 1)
                var pixel = imageData.data
                var r = pixel[0]
                var g = pixel[1]
                var b = pixel[2]
                var a = pixel[3] / 255
                a = Math.round(a * 100) / 100
                var rHex = r.toString(16)
                r < 16 && (rHex = '0' + rHex)
                var gHex = g.toString(16)
                g < 16 && (gHex = '0' + gHex)
                var bHex = b.toString(16)
                b < 16 && (bHex = '0' + bHex)
                var rgbaColor = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'
                var rgbColor = 'rgb(' + r + ',' + g + ',' + b + ')'
                var hexColor = '#' + rHex + gHex + bHex
                glasscanp.innerText = hexColor
                self.hexColor = hexColor
                var drawWidth = 50,
                  drawHeight = 50
                glassContext.drawImage(img, self.mouse.x - drawWidth / 4 + 4, self.mouse.y - drawHeight / 4 + 6, drawWidth, drawHeight, 0, 0, drawWidth * 16, drawHeight * 16) // 实现放大镜
              }
              // 绑定鼠标移出事件
              imgcan.onmouseout = function() {
                glasscan.style.display = 'none'
                glasscanimg.style.display = 'none'
                glasscanp.style.display = 'none'
              }
              imgcan.onmouseover = function() {
                if (self.glass == true) {
                  glasscan.style.display = 'block'
                  glasscanimg.style.display = 'block'
                  glasscanp.style.display = 'block'
                  imgcan.style.display = 'block'
                }
              }
              imgcan.onclick = function() {
                self.$emit('active-change', self.hexColor)
                var fcolorpicker = document.querySelector('.fcolorpicker-curbox')
                fcolorpicker.style.backgroundColor = self.hexColor
                this.option.color = self.hexColor
                console.log(self.hexColor)
                self.glass = false
                imgcan.style.display = 'none'
                glasscan.style.display = 'none'
                glasscanimg.style.display = 'none'
                glasscanp.style.display = 'none'
              }
            } else {
              var imgcan = document.querySelector('#imgcan')
              imgcan.style.display = 'none'
            }
          }
        })
      })
    }
  },
  computed: {
    ...mapState({
      fObj: state => state.fabricStore.fabricObject,
      fJson: state => state.fabricStore.fabricJson,
      fAct: state => state.fabricStore.fabricAcitveObjects,
      fActO: state => state.fabricStore.fabricAcitveObject,
      loginInfo: state => state.app.loginInfo
    })
  },
  // beforeDestroy() {
  //   if (!this.sameColor(this.oldValue, this.color)) {
  //     this.$emit('closePicker', this.oldValue)
  //   }
  // },
  mounted() {
    this.domId = 'dom-' + ((new Date()).getTime() + Math.random()).toString().replace('.', '')
    if (this.color.type == 'linear') {
      var zhuanhuan = this.fActO.fill.colorStops.map((e) => {
        return `${e.color} ${e.per}%`
      })
      var color = `linear-gradient(0.0deg,${zhuanhuan})`
    } else {
      var color = this.color == '' ? '#ffffff' : this.color
    }
    console.log('fill', this.fActO.fill)
    console.log(color)
    this.$nextTick(() => {
      var self = this
      var xncolorpicker = new XNColorPicker({
        color: color,
        selector: '#' + this.domId,
        showprecolor: true, // 显示预制颜色
        prevcolors: null, // 预制颜色,不设置则默认
        showhistorycolor: false, // 显示历史
        historycolornum: 16, // 历史条数
        format: 'hex', // rgba hex hsla,初始颜色类型
        showPalette: true, // 显示色盘
        show: false, // 初始化显示
        lang: 'cn', // cn 、en
        colorTypeOption: 'single,linear-gradient,radial-gradient',
        canMove: false, // 选择器位置是否可以拖拽
        alwaysShow: false,
        autoConfirm: true,
        onError: function(e) {

        },
        onCancel: function(color) {
          console.log('cancel', color)
        },
        onChange: function(color) {
          self.$emit('active-change', color.color.hex)
          // console.log('change', color)
          if (color.colorType == 'single') {
            self.$emit('active-change', color.color.hex)
          } else if (color.colorType == 'linear-gradient') {
            // self.$emit('active-change', color.color.str)
            self.linear(color)
          } else {
            // self.$emit('active-change', color.color.str)
            self.radial(color)
          }
        },
        onConfirm: function(color) {
          console.log(color)
          self.$emit('active-change', color.color.hex)
          // console.log('change', color)
          if (color.colorType == 'single') {
            self.$emit('active-change', color.color.hex)
          } else if (color.colorType == 'linear-gradient') {
            // self.$emit('active-change', color.color.str)
            self.linear(color)
          } else {
            // self.$emit('active-change', color.color.str)
            self.radial(color)
          }
        },
        openSucker: function(color) {
          self.glass = true
          if (color == 1) {
            var imgcan = document.querySelector('#imgcan')
            imgcan.style.display = 'block'
            var glasscan = document.getElementById('glasscan')
            var glasscanimg = document.getElementById('glasscanimg')
            var glasscanp = document.getElementById('glasscanp')
            var imgContext = document.querySelector('#canvas').getContext('2d')
            var glassContext = glasscan.getContext('2d')
            var img = new Image()
            self.mouse = captureMouse(imgcan)
            img.src = self.fObj.toDataURL({ multiplier: 1, withoutTransform: true })
            img.onload = function() {
              imgContext.drawImage(img, self.fObj.width, self.fObj.height)
            }
            // 获取元素内鼠标位置
            function captureMouse(element) {
              element.addEventListener('mousemove', function(event) {
                var x = event.pageX
                var y = event.pageY
                if (event.type == 'touchstart') {
                  x = event.touches[0].clientX
                  y = event.touches[0].clientY
                }
                var canvas = event.target
                self.mouse = self.getPointOnCanvas(canvas, x, y)
              }, false)
            }
            // 给画布绑定鼠标移动事件
            imgcan.onmousemove = function() {
              glassContext.clearRect(0, 0, glasscan.width, glasscan.height)
              glasscan.style.left = self.mouse.x + 'px'
              glasscan.style.top = self.mouse.y + 'px'
              glasscanimg.style.left = self.mouse.x + 'px'
              glasscanimg.style.top = self.mouse.y + 'px'
              glasscanp.style.left = self.mouse.x + 90 + 'px'
              glasscanp.style.top = self.mouse.y + 180 + 'px'
              // 显示鼠标位置
              // console.log(self.mouse.x, self.mouse.y)
              // console.log(imgContext.getImageData(self.mouse.x, self.mouse.y, 1, 1).data)
              var imageData = imgContext.getImageData(self.mouse.x, self.mouse.y, 1, 1)
              var pixel = imageData.data
              var r = pixel[0]
              var g = pixel[1]
              var b = pixel[2]
              var a = pixel[3] / 255
              a = Math.round(a * 100) / 100
              var rHex = r.toString(16)
              r < 16 && (rHex = '0' + rHex)
              var gHex = g.toString(16)
              g < 16 && (gHex = '0' + gHex)
              var bHex = b.toString(16)
              b < 16 && (bHex = '0' + bHex)
              var rgbaColor = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'
              var rgbColor = 'rgb(' + r + ',' + g + ',' + b + ')'
              var hexColor = '#' + rHex + gHex + bHex
              glasscanp.innerText = hexColor
              self.hexColor = hexColor
              var drawWidth = 50,
                drawHeight = 50
              glassContext.drawImage(img, self.mouse.x - drawWidth / 4 + 4, self.mouse.y - drawHeight / 4 + 6, drawWidth, drawHeight, 0, 0, drawWidth * 16, drawHeight * 16) // 实现放大镜
            }
            // 绑定鼠标移出事件
            imgcan.onmouseout = function() {
              glasscan.style.display = 'none'
              glasscanimg.style.display = 'none'
              glasscanp.style.display = 'none'
            }
            imgcan.onmouseover = function() {
              if (self.glass == true) {
                glasscan.style.display = 'block'
                glasscanimg.style.display = 'block'
                glasscanp.style.display = 'block'
                imgcan.style.display = 'block'
              }
            }
            imgcan.onclick = function() {
              self.$emit('active-change', self.hexColor)
              console.log(self.hexColor)
              var fcolorpicker = document.querySelector('.fcolorpicker-curbox')
              fcolorpicker.style.backgroundColor = self.hexColor
              self.glass = false
              imgcan.style.display = 'none'
              glasscan.style.display = 'none'
              glasscanimg.style.display = 'none'
              glasscanp.style.display = 'none'
            }
            var mainbody = document.querySelector('.mainbody')
            mainbody.onclick = function() {
              self.glass = false
              imgcan.style.display = 'none'
              glasscan.style.display = 'none'
              glasscanimg.style.display = 'none'
              glasscanp.style.display = 'none'
            }
          } else {
            var imgcan = document.querySelector('#imgcan')
            imgcan.style.display = 'none'
          }
        }
      })
    })

  },
  methods: {
    activeChangeColor(val) {
      this.$emit('active-change', val)
    },
    sameColor(c1, c2) {
      var rgb1 = c1.colorRgb()
      if (rgb1.indexOf('rgba') < 0) {
        rgb1 = rgb1.replace('rgb', 'rgba')
        rgb1 = rgb1.substr(0, rgb1.length - 1) + ',1)'
      }
      rgb1 = rgb1.replace('rgba(', '').replace(')', '').split(',')
      var rgb2 = c2.colorRgb()
      if (rgb2.indexOf('rgba') < 0) {
        rgb2 = rgb2.replace('rgb', 'rgba')
        rgb2 = rgb2.substr(0, rgb2.length - 1) + ',1)'
      }
      rgb2 = rgb2.replace('rgba(', '').replace(')', '').split(',')
      return (rgb1[0].trim() == rgb2[0].trim() && rgb1[1].trim() == rgb2[1].trim() && rgb1[2].trim() == rgb2[2].trim() && rgb1[3].trim() == rgb2[3].trim())
    },
    getPointOnCanvas(canvas, x, y) {
      var bbox = canvas.getBoundingClientRect()
      return {
        x: (x - bbox.left) * (canvas.width / bbox.width) - document.body.scrollLeft,
        y: (y - bbox.top) * (canvas.height / bbox.height) - document.body.scrollTop
      }
    },
    linear(item) {
      console.log(item)
      item.color.arry.colors.forEach(val => {
        val.offset = val.per / 100
      })
      const o = this.fActO
      const gradientLinear = new fabric.Gradient({
        type: 'linear',
        coords: {
          x1: 0,
          y1: 0,
          x2: o.width,
          y2: o.height
        },
        gradientUnits: 10, // 调色 字体百分比
        colorStops: item.color.arry.colors,
        value: item
      })
      o.set('fill', gradientLinear)
      this.fObj.renderAll()
    },
    radial(item) {
      item.color.arry.colors.forEach(val => {
        val.offset = val.per / 100
      })
      const o = this.fActO
      const gradientRadial = new fabric.Gradient({
        type: 'radial',
        coords: {
          x1: o.width / 2,
          y1: o.height / 2,
          x2: o.width / 2,
          y2: o.height / 2,
          r1: o.height / 2,
          r2: o.width / 2
        },
        gradientUnits: 10, // 调色 字体百分比
        colorStops: item.color.arry.colors
      })
      o.set('fill', gradientRadial)
    },
    selectGradient(item) {
      const o = this.fActO
      if (o) {
        if (item.colorE && item.color) {
          item.gradientLinear = new fabric.Gradient({
            type: 'linear',
            coords: {
              x1: 0,
              y1: 0,
              x2: o.width,
              y2: o.height
            },
            gradientUnits: 10, // 调色 字体百分比
            colorStops: [{
              offset: 0,
              color: item.color
            }, {
              offset: 1,
              color: item.colorE
            }]
          })
          item.gradientRadial = new fabric.Gradient({
            type: 'radial',
            coords: {
              x1: o.width / 2,
              y1: o.height / 2,
              x2: o.width / 2,
              y2: o.height / 2,
              r1: o.height / 2,
              r2: o.width / 2
            },
            gradientUnits: 10, // 调色 字体百分比
            colorStops: [{
              offset: 0,
              color: item.color
            }, {
              offset: 1,
              color: item.colorE
            }]
          })
          if (this.value === 1) {
            o.set('fill', item.gradientLinear)
          } else if (this.value === 2) {
            o.set('fill', item.gradientRadial)
          } else if (this.value === 0) {
            o.set('fill', '#000')
          }
        }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

2.放置所需js以及样式 1.colorpicker.js 代码比较多我就不贴了