vue3如何改变svg字体大小,以及子组件如何改变父组件背景色

1、hanzi-write生成的svg只能使用px像素大小,使用rem无效。2、子组件无法修改父组件背景色。

svg问题:

<template>
  
  <div class="header">
    
    <div v-for="item of 200" :key="item" class="snowflake">div>
    <div class="title">
      
      <div class="title__parent">
        <Transition
          name="fade"
          enter-active-class="animate__animated animate__slideInUp"
        >
          <p v-if="show" class="title__top">驶出孤岛p>
        Transition>
      div>
      <div class="title__row">
        <div class="title__parent">
          <Transition
            name="fade"
            enter-active-class="animate__animated animate__slideInUp animate__fast delay"
          >
            <p v-if="show" class="title__row__left">p>
          Transition>
        div>
        
        <div class="title__row__right">
          <div id="character-target-div">div>
        div>
      div>
    div>
  div>
template>
<script>
import { onMounted, ref } from "vue";
import HanziWriter from "hanzi-writer";
export default {
  name: "Header",
  setup() {
    const show = ref(false);
    const chainAnimations = () => {
      //创建笔法“淘”字实例
      var writeOne = HanziWriter.create("character-target-div", "淘", {
        width: 150, //宽
        height: 150, //高
        padding: 5, //内边距
        showCharacter: false, //不显示汉字
        showOutline: false, //开启动画时不显示汉字
        strokeColor: "#000000", //字体颜色
        strokeAnimationSpeed: 5, //动画速度
        delayBetweenStrokes: 10, //动画每笔间隔时间,默认1000
      });

      //创建笔法“金”字实例
      var writeTwo = HanziWriter.create("character-target-div", "金", {
        width: 150, //宽
        height: 150, //高
        padding: 5, //内边距
        showCharacter: false, //不显示汉字
        showOutline: false, //开启动画时不显示汉字
        strokeColor: "#000000", //字体颜色
        strokeAnimationSpeed: 5, //动画速度
        delayBetweenStrokes: 10, //动画每笔间隔时间,默认1000
        drawingWidth: 10,
      });

      //创建笔法“者”字实例
      var writeThree = HanziWriter.create("character-target-div", "者", {
        width: 150, //宽
        height: 150, //高
        padding: 5, //内边距
        showCharacter: false, //不显示汉字
        showOutline: false, //开启动画时不显示汉字
        strokeColor: "#000000", //字体颜色
        strokeAnimationSpeed: 5, //动画速度
        delayBetweenStrokes: 10, //动画每笔间隔时间,默认1000
      });

      setTimeout(function () {
        writeOne.animateCharacter({
          onComplete: function () {
            setTimeout(function () {
              writeTwo.animateCharacter({
                onComplete: function () {
                  setTimeout(function () {
                    writeThree.animateCharacter();
                  }, 0);
                },
              });
            }, 0);
          },
        });
      }, 980);

    };
//挂载执行
    onMounted(() => {
      show.value = true;
      chainAnimations();
    });

    return { show };
  },
};
script>

<style lang="scss" scoped>
* {
  margin: 0;
  box-sizing: border-box;
}

#character-target-div {
  height: 100%;
}

#character-target-div svg {
  width: 1.6rem;
}

.header {
  width: 100%;
  height: 150vh;
  display: flex;
  justify-content: center;
  background: linear-gradient(
    to top,
    #fffbf7 40%,
    #fff5f5 50%,
    rgb(255, 218, 218) 99%
  ) !important;

  .title {
    width: 90%;
    height: 3.56rem;
    margin: 2.8rem 0 0 0;
    letter-spacing: 0.5rem;
    &__parent {
      display: block;
      overflow: hidden;
    }
    &__top {
      display: block;
      font-size: 1.496rem;
      font-family: 宋体;
      font-weight: bold;
      margin-left: 1rem;
    }
    &__row {
      display: flex;
      justify-content: flex-end;
      &__left {
        color: #000000;
        font-size: 1.496rem;
        font-family: 宋体;
        padding-right: 0.2rem;
      }
      &__right {
        color: #000;
        height: 1.5rem;
        font-size: 1.5rem;
        font-family: "Lucida Calligraphy", cursive, serif, sans-serif;
        padding-right: 0.5rem;
      }
    }
  }
}

.snowflake {
  --size: 1vw;
  width: var(--size);
  height: var(--size);
  background: url(../../images/falling.gif) no-repeat; //金色叶子
  background-size: 100% 100%;
  position: fixed;
  top: -10vh; //出事高度在屏幕外 效果更真实
  z-index: 1; //背景图层不遮挡上面元素
}

@keyframes fall {
  100% {
    transform: translate3d(var(--end), 100vh, 0);
  }
}

@for $i from 0 through 200 {
  .snowflake:nth-child(#{$i}) {
    //每个雪花的大小
    --size: #{random(6) * 0.1}vw;
    //雪花移动目标点
    --end: #{random(20) - 40}vw;
    //雪花初始位置
    left: #{random(150)}vw;
    //雪花从顶到底移动的动画 动画时间可以调整雪花速度
    animation: fall #{5 + random(8)}s linear infinite;
    animation-delay: -#{random(10)}s;
  }
}

.animate__slideInUp {
  animation-duration: 0.9s;
}

.delay {
  animation-duration: .98s;
  animation-delay: 350ms;
}

style>

父组件:

<template>
  <div 
    id="js-main-bg" 
    class="c-main-bg"
  >
    <Footer />
  div>
template>

<script>
import Footer from "../footer/Footer";
export default {
  name: "ContentMain",
  components: {
    Footer,
  },
  setup() {
    const mainBg = document.getElementById("js-main-bg");
    return {
      mainBg
    }
  },
};
script>

<style lang="scss" scoped>
.c-main-bg {
  height: 450vh;
  background-color: #f2f2f2;
  padding: 1.2rem 1rem 0.4rem;
style>

子组件:

<template>
  <div class="section">
    <div class="section__row">
      <div class="section__row__left">
        <img
          src="../../images/pc1.jpg"
          alt=""
        />
      div>
      <div class="section__row__right">
        <img
          src="../../images/pc2.jpg"
          alt=""
        />
      div>
    div>
  div>
template>

<script>
import { mainBg } from "../contentMain/ContentMain";
export default {
  name: "Footer",
};
script>

<style lang="scss" scoped>
.section {
  display: flex;
  align-items: center;
  height: 200vh;
  &__row {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    &__left {
      width: 55%;
      display: flex;
      justify-content: flex-end;
    }
    &__right {
      width: 32%;
      transform: translate(-20%);
      display: flex;
      justify-content: flex-end;
    }
  }
  img {
    width: 100%;
    border-radius: 0.5rem;
  }
  img:hover {
      filter: saturate(0);
      transition: .6s cubic-bezier(0,.89,.41,1);
    }
}
style>
我想要达到的效果。1、修改hanzi-write生成的svg字体大小样式为rem。2、鼠标移入子组件的两个图片,父组件的背景色变为其他颜色,移出后还原。

希望能够给出有效的解决方案,感激不尽!

亲测解决了这两个问题,解决方案如下:
问题1:
svg父元素的宽高可以设置成rem,调用HanziWriter.create时,不传 width、height,这样svg画布大小宽高就是100%
1.style中

#character-target-div {
  width: 5rem;
  height: 5rem;
}

2.script中,创建笔法实例时 都把width height去掉

//创建笔法“淘”字实例
      var writeOne = HanziWriter.create("character-target-div", "淘", {
        padding: 5, //内边距
        showCharacter: false, //不显示汉字
        showOutline: false, //开启动画时不显示汉字
        strokeColor: "#000000", //字体颜色
        strokeAnimationSpeed: 5, //动画速度
        delayBetweenStrokes: 10, //动画每笔间隔时间,默认1000
      });

问题2:
通过自定义事件,达到子组件修改父组件样式的效果
1.ContentMain.vue


<template>
  <div
    id="js-main-bg"
    class="c-main-bg"
    :style="{ backgroundColor: isHover ? 'green' : '#f2f2f2' }"
  >
    <fooCom @hoverImg="(flag) => (isHover = flag)" />
  </div>
</template>

<script>
import fooCom from "./components/footer.vue";
import { ref } from "vue";
export default {
  name: "ContentMain",
  components: {
    fooCom,
  },
  setup() {
    const isHover = ref(false);
    return {
      isHover,
    };
  },
};
</script>
<style lang="scss" scoped>
.c-main-bg {
  height: 450vh;
  background-color: #f2f2f2;
  padding: 1.2rem 1rem 0.4rem;
}
</style>

2.footer.vue

<template>
  <div class="section">
    <div class="section__row">
      <div class="section__row__left">
        <img
          src="../../images/pc1.jpg"
          alt=""
          @mouseenter="$emit('hoverImg', true)"
          @mouseleave="$emit('hoverImg', false)"
        />
      </div>
      <div class="section__row__right">
        <img
          src="../../images/pc2.jpg"
          alt=""
          @mouseenter="$emit('hoverImg', true)"
          @mouseleave="$emit('hoverImg', false)"
        />
      </div>
    </div>
  </div>
</template>

<script></script>

<style lang="scss" scoped>
.section {
  display: flex;
  align-items: center;
  height: 200vh;
  &__row {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    &__left {
      width: 55%;
      display: flex;
      justify-content: flex-end;
    }
    &__right {
      width: 32%;
      transform: translate(-20%);
      display: flex;
      justify-content: flex-end;
    }
  }
  img {
    width: 100%;
    border-radius: 0.5rem;
  }
  img:hover {
    filter: saturate(0);
    transition: 0.6s cubic-bezier(0, 0.89, 0.41, 1);
  }
}
</style>


该回答引用ChatGPT
请参考下面的解决方案,如果可行 还请点击采纳,感谢!

问题1:
可以在使用 hanzi-write 生成的 SVG 字体的父元素上设置 font-size 属性,并使用 CSS 的 rem 单位:
可以通过修改父元素的 font-size 来控制生成的 SVG 字体的大小,而不会影响其他的字体大小。

<template>
  <div>
    <hanzi-write
      :hanzi="hanzi"
      :width="width"
      :height="height"
    />
  </div>
</template>

<script>
import HanziWrite from 'hanzi-write';

export default {
  components: {
    HanziWrite
  },
  data() {
    return {
      hanzi: '你',
      width: 100,
      height: 100
    };
  }
};
</script>

<style>
div {
  font-size: 2rem;
}
</style>

、、、、、、、、、、、、、、、
问题2:
你可以在子组件中使用@mouseenter和@mouseleave事件来触发父组件的方法,从而改变父组件的背景色。以下是一个示例代码:
子组件

<template>
  <img 
    @mouseenter="changeBgColor('#ff0000')" 
    @mouseleave="changeBgColor('#ffffff')" 
    src="your-img-src" 
    alt="your-img-alt">
</template>

<script>
export default {
  methods: {
    changeBgColor(color) {
      this.$emit('change-bg-color', color)
    }
  }
}
</script>

父组件:

<template>
  <div :style="{ backgroundColor: bgColor }">
    <your-component @change-bg-color="changeBgColor"></your-component>
  </div>
</template>

<script>
import YourComponent from 'path-to-your-component'

export default {
  components: {
    YourComponent
  },
  data() {
    return {
      bgColor: '#ffffff'
    }
  },
  methods: {
    changeBgColor(color) {
      this.bgColor = color
    }
  }
}
</script>


不知道你解决了没?
如果没解决,我们可以聊聊。

第一个问题:
先看看控制台svg的font-size是什么,如果设置成功,应该是有font-size,数值为rem转化后的px值;
第二个问题:
子组件用@mouseenter和@mouseleave监听事件,用$emit触发父组件事件,在父组件事件里面改背景色,具体代码不懂的可以问我;

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

提供参考实例,链接:https://blog.csdn.net/weixin_42204698/article/details/93751906