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

svg颜色修改

前言

大家好,我是yma16,本文分享关于svg在vue3中修改颜色代码的实现

效果

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

灵感来源

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

  • 点击颜色可以不停的刷新最近使用的颜色值
  • 可以使用16进制的颜色参数
  • 可以下拉调整大小

html渲染svg

HTML 可以通过内嵌 SVG 文件或使用 <img> 标签加载 SVG 文件来渲染 SVG 图像。

内嵌 SVG 文件:

arduino 复制代码
<svg width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="red" />
</svg>

上述代码在 HTML 中嵌入一个圆形的 SVG 图像,并使用 widthheight 属性指定宽度和高度。

使用 <img> 标签加载 SVG 文件:

ini 复制代码
<img src="image.svg" alt="SVG image">

上述代码使用 <img> 标签加载名为 image.svg 的 SVG 文件,并使用 alt 属性指定图像的替代文本。

可以使用 CSS 样式对 SVG 图像进行样式设置,类似于对 HTML 元素进行样式设置。例如,可以为 SVG 图像设置背景颜色、边框、外边距等。

xml 复制代码
<style>
  svg {
    background-color: #fff;
    border: 1px solid #ccc;
    margin: 10px;
  }
</style>

css修改svg

在 CSS 中,可以使用 fill 和 stroke 属性来设置 SVG 元素的颜色。

下面是一些常见的用法:

  1. 修改填充颜色:
css 复制代码
svg path {
  fill: #ff0000;
}
  1. 修改描边颜色:
css 复制代码
svg path {
  stroke: #00ff00;
}
  1. 同时修改填充和描边颜色:
css 复制代码
svg path {
  fill: #ff0000;
  stroke: #00ff00;
}
  1. 渐变填充:

可以使用 CSS 渐变来为 SVG 元素设置渐变填充,如下所示:

ini 复制代码
svg path {
  fill: url(#myGradient);
}

<svg>
  <defs>
    <linearGradient id="myGradient">
      <stop offset="0%" stop-color="#ff0000" />
      <stop offset="100%" stop-color="#0000ff" />
    </linearGradient>
  </defs>
  <path d="M0 0 L100 0 L100 100 Z" />
</svg>

其中,linearGradient 定义了一个线性渐变,stop 元素用于定义渐变的起始和结束颜色。在 SVG 元素中,使用 fill 属性指定渐变。

思路

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

代码如下:

javascript 复制代码
 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})`;
        }

实现

模拟一个数组栈,先进后出记录颜色值。

代码如下:

javascript 复制代码
/* 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>

我的代码仓库

本文分享到此结束,感谢你的阅读,如有不足或者错误欢迎指出

传送门:codechina.csdn.net/qq_38870145...

相关推荐
Dread_lxy27 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
前端郭德纲2 小时前
浏览器是加载ES6模块的?
javascript·算法
JerryXZR2 小时前
JavaScript核心编程 - 原型链 作用域 与 执行上下文
开发语言·javascript·原型模式
帅帅哥的兜兜2 小时前
CSS:导航栏三角箭头
javascript·css3
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
龙猫蓝图2 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
夜色呦3 小时前
掌握ECMAScript模块化:构建高效JavaScript应用
前端·javascript·ecmascript
peachSoda73 小时前
随手记:简单实现纯前端文件导出(XLSX)
前端·javascript·vue.js