vue3_制作一个在线修改svg颜色功能

简介: vue3_制作一个在线修改svg颜色功能

效果

可点击色块切换svg的颜色,可记录前七种选择的颜色和当前选择的色号
image.png

image.png

灵感来源

来源阿里图标库的在线修改svg颜色功能
image.png

思路

利用img标签产生一个shadow阴影,再使用transform把原图移走,达到替换svg颜色的效果

 if (state.colorValue) {
          document.getElementById("design-svg-id").style.transform = `translate(-500px)`;
          document.getElementById(
            "design-svg-id"
          ).style.filter = `drop-shadow(500px 0 0 ${state.colorValue})`;
        }

实现

/* eslint-disable vue/valid-v-model */
<template>
  <div class="design">
    <div class="design-img">
      <img src="../../assets/logo.svg" id="design-svg-id" />
    </div>
    <div class="design-color-extract" :ref="extractRef" id="extract-id"></div>
    <div class="design-color-select-box">
      <div class="design-color-select-box-record" :ref="selecttRef" id="select-id"></div>
      <div class="design-color-select-box-focus">
        <div class="design-color-select-box-focus-color-value">{{ colorValue }}</div>
        <div class="design-color-select-box-focus-box" id="select-color-box-id"></div>
      </div>
      <!-- <div class="design-color-select-box-svg-size">
        <a-input-number
          id="inputNumber"
          v-model:value="sizeValue"
          :min="1"
          :max="10"
          class="design-color-select-box-svg-size-input"
        />
      </div> -->
    </div>
    <div class="design-color-quick-extract"></div>
  </div>
</template>

<script>
import { ref, onMounted, reactive, toRefs, watch } from "vue";
export default {
  name: "DesignSvg",
  props: {},
  setup() {
    const state = reactive({
      sizeValue: ref(0),
      colorValue: ref("#"),
      colorArray: [
        "d81e06",
        "f4ea2a",
        "1afa29",
        "1296db",
        "13227a",
        "d4237a",
        "ffffff",
        "e6e6e6",
        "dbdbdb",
        "cdcdcd",
        "bfbfbf",
        "8a8a8a",
        "707070",
        "515151",
        "2c2c2c",
      ],
      colorSelected: [
        "e6e6e6",
        "dbdbdb",
        "cdcdcd",
        "bfbfbf",
        "8a8a8a",
        "707070",
        "515151",
        "2c2c2c",
      ],
      colorDomSelect: [],
      colorDomRecord: [],
    });
    const extractRef = ref(null);
    const selecttRef = ref(null);
    onMounted(() => {
      // 选择颜色
      initBoxColor();
      // 历史选择颜色
      initBoxSelected();
      // 选择的数组
      console.log("domSelect", state.colorDomSelect);
      console.log("domRecord", state.colorDomRecord);
      initClick();
    });
    // 获取颜色
    function initBoxColor() {
      state.colorArray.map((item) => {
        let singleBoxColor = document.createElement("div");
        singleBoxColor.className = "box";
        singleBoxColor.style.background = "#" + item;
        state.colorDomSelect.push(singleBoxColor);
        document.getElementById("extract-id").appendChild(singleBoxColor);
      });
    }
    // 容器记录选中的颜色
    function initBoxSelected() {
      state.colorSelected.map((item) => {
        let singleBoxColor = document.createElement("div");
        singleBoxColor.className = "box";
        singleBoxColor.style.background = "#" + item;
        state.colorDomRecord.push(singleBoxColor);
        document.getElementById("select-id").appendChild(singleBoxColor);
      });
    }
    // 添加事件 修改color
    function initClick() {
      state.colorDomSelect.map((item, index) => {
        item.addEventListener("click", function () {
          // color
          state.colorValue = "#" + state.colorArray[index];
          document.getElementById(
            "select-color-box-id"
          ).style.background = `${state.colorValue}`;
          // record
          if (state.colorSelected.includes(state.colorArray[index])) {
            console.log("have");
          } else {
            // 加入数组第一个
            let length = state.colorSelected.length;
            for (let loc = length - 1; loc > -1; --loc) {
              if (loc === 0) {
                // 第一个元素
                state.colorSelected[loc] = state.colorArray[index];
              } else {
                // 后移一位
                state.colorSelected[loc] = state.colorSelected[loc - 1];
              }
              // 替换颜色
              state.colorDomRecord[loc].style.background = "#" + state.colorSelected[loc];
            }
            // console.log("state.colorDomRecord", state.colorDomRecord);
          }
        });
      });
    }
    // 监听颜色变化
    watch(
      () => state.colorValue,
      () => {
        if (state.colorValue) {
          document.getElementById("design-svg-id").style.transform = `translate(-500px)`;
          document.getElementById(
            "design-svg-id"
          ).style.filter = `drop-shadow(500px 0 0 ${state.colorValue})`;
        }
      }
    );
    // 监听svg大小变化
    watch(
      () => state.sizeValue,
      () => {
        console.log("size", document.getElementById("design-svg-id").style.transform);
        if (state.sizeValue > 0) {
          let num = state.sizeValue * 0.1 + 1;
          document.getElementById("design-svg-id").style.transform = `scale(${num})`;
        } else {
          state.sizeValue = 1;
        }
      }
    );
    return { ...toRefs(state), extractRef, selecttRef };
  },
};
</script>

<style>
.design {
  position: relative;
  width: 100%;
  height: 100%;
  background: rgba(241, 193, 164, 0.603));
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 1px 20px rgba(0, 0, 0, 0.1);
}
.design-img {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 300px;
}
.design-color-extract {
  position: relative;
  display: flex;
  height: 60px;
}
.design-color-select-box {
  position: relative;
  display: flex;
}
.design-color-select-box-record {
  position: relative;
  display: flex;
  width: 50%;
  height: 60px;
}
.design-color-quick-extract {
  position: relative;
  height: 60px;
}
.design-color-select-box-focus {
  position: relative;
  margin-left: 10px;
  width: 110px;
  height: 50px;
  border: 1px solid #444;
  display: flex;
  background: #fff;

  box-shadow: 0 1px 20px rgba(0, 0, 0, 0.2);
}
.design-color-select-box-focus-box {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 25px;
  border: 1px solid #444;
  margin-left: 20px;
  width: 25px;
}
.design-color-select-box-focus-color-value {
  position: relative;
  width: 60px;
  margin-left: 2px;
  top: 50%;
  transform: translateY(-50%);
  height: 25px;
  border: 1px solid #444;
  text-align: left;
}
.design-color-select-box-svg-size {
  position: relative;
  margin-left: 10px;
  width: 100px;
  height: 50px;
  border: 1px solid #444;
  overflow: hidden;
  box-sizing: border-box;
}

.design-color-select-box-svg-size-input {
  position: relative;
  outline: none;
  text-align: center;
  width: 100%;
  height: 100%;
}
.box {
  position: relative;
  width: 40px;
  height: 40px;
  cursor: pointer;
}
</style>

我的代码仓库

传送门:https://codechina.csdn.net/qq_38870145/edit_svg
image.png

目录
相关文章
|
10天前
|
存储 JavaScript 前端开发
vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!
【10月更文挑战第21天】 vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!
vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!
|
7天前
|
JavaScript 前端开发 开发者
Vue 3中的Proxy
【10月更文挑战第23天】Vue 3中的`Proxy`为响应式系统带来了更强大、更灵活的功能,解决了Vue 2中响应式系统的一些局限性,同时在性能方面也有一定的提升,为开发者提供了更好的开发体验和性能保障。
20 7
|
8天前
|
前端开发 数据库
芋道框架审批流如何实现(Cloud+Vue3)
芋道框架审批流如何实现(Cloud+Vue3)
28 3
|
7天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
26 1
|
7天前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
27 1
|
10天前
|
前端开发 JavaScript
简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef
简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef
|
10天前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。
|
14天前
|
JavaScript API
vue3知识点:ref函数
vue3知识点:ref函数
26 2
|
14天前
|
API
vue3知识点:reactive函数
vue3知识点:reactive函数
24 1
|
14天前
|
JavaScript 前端开发 API
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
22 0