Skip to content

字体颜色随背景色变化

filter 滤镜

文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
vue
<template>
  <div v-for="color of colors" :style="{ backgroundColor: color, color }" class="box">
    <span class="filter">文字文字</span>
  </div>
</template>

<script setup>
const colors = [
  '#775039',
  '#8b7042',
  '#fff799',
  '#b1d5c8',
  '#007175',
  '#3271ae',
  '#a6559d',
  '#d5ebe1',
  '#80a492',
  '#422517'
]
</script>

<style lang="scss" scoped>
.box {
  display: inline-block;
  width: 50%;
  height: 100px;
  line-height: 100px;
  text-align: center;
  font-size: 30px;
}
.filter {
  filter: grayscale(1) contrast(999) invert(1);
}
</style>

mix-blend-mode 混合模式

文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
文字文字
vue
<template>
  <div v-for="color of colors" :style="{ backgroundColor: color }" class="box">
    <span class="mix">文字文字</span>
  </div>
  <div class="box" style="background-image: linear-gradient(45deg, black 50%, transparent 0)">
    <span class="mix">文字文字</span>
  </div>
  <div class="box" style="background-image: linear-gradient(45deg, red 50%, yellow 0)">
    <span class="mix">文字文字</span>
  </div>
</template>

<script setup>
const colors = [
  '#775039',
  '#8b7042',
  '#fff799',
  '#b1d5c8',
  '#007175',
  '#3271ae',
  '#a6559d',
  '#d5ebe1',
  '#80a492',
  '#422517'
]
</script>

<style lang="scss" scoped>
.box {
  display: inline-block;
  width: 50%;
  height: 100px;
  line-height: 100px;
  text-align: center;
  font-size: 30px;
}
.mix {
  color: #fff;
  mix-blend-mode: difference;
}
</style>

canvas

文字文字
文字文字
文字文字
vue
<template>
  <div v-for="img of images" :style="{ backgroundImage: `url(${img.src})`, color: img.color }" class="box">
    <span class="filter">文字文字</span>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'

const images = reactive([
  { src: 'https://tse3-mm.cn.bing.net/th/id/OIP-C.7KW5GT7NQ8yUGlBbCHEm0gHaNK?pid=ImgDet&rs=1', color: '#fff' },
  {
    src: 'https://s.cn.bing.net/th?id=OHR.Mohair_ZH-CN9435762268_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&qlt=50',
    color: '#fff'
  },
  {
    src: 'https://img.youpin.mi-img.com/ferriswheel/e4d49589_16c6_434b_992c_93e232edff2b.jpeg@base@tag=imgScale&F=webp&h=1320&q=90&w=1080',
    color: '#fff'
  }
])

onMounted(() => {
  for (const img of images) {
    getThemeColor(img)
  }
})

function readBlob(blob) {
  return new Promise((res, rej) => {
    const reader = new FileReader()
    reader.addEventListener('load', () => res(reader.result))
    reader.addEventListener('error', () => rej(reader.result))
    reader.readAsDataURL(blob)
  })
}

function loadImg(src) {
  return new Promise((res, rej) => {
    const img = document.createElement('img')
    img.addEventListener('load', () => res(img))
    img.addEventListener('error', () => rej(img))
    img.src = src
  })
}

function getColor(img) {
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  canvas.width = 10
  canvas.height = 10
  ctx.drawImage(img, 0, 0, 10, 10)
  const { data } = ctx.getImageData(0, 0, 10, 10)
  let r = 0,
    g = 0,
    b = 0
  for (let i = 0; i < 400; i += 4) {
    r += data[i]
    g += data[i + 1]
    b += data[i + 2]
  }
  return `rgb(${r / 100}, ${g / 100}, ${b / 100})`
}

function getThemeColor(row) {
  fetch(row.src)
    .then(res => res.blob())
    .then(readBlob)
    .then(loadImg)
    .then(getColor)
    .then(res => {
      row.color = res
    })
}
</script>

<style lang="scss" scoped>
.box {
  padding: 8px;
  font-size: 30px;
  height: 200px;
  background-clip: content-box;
  background-size: cover;
  background-position: center;
}
.filter {
  filter: grayscale(1) contrast(999) invert(1);
}
</style>