three实现文字描边label

使用 text-shadow

设置宽度设置为>1时,效果不太好,像重影。(可能是哪里没考虑到吧)
正常效果:正常效果
重影效果:重影效果重影效果

使用 text-stroke 描边

做了处理也还是存在描边覆盖问题,背景色在填充色上面:
描边覆盖

function generateLabel (options: any) {
  const { id, position, fontSize, fillColor, text, pixelOffset, outlineColor, outlineWidth, scaleByDistance } = options
  const textDiv = document.createElement('div')
  const shadowColor = outlineColor ? outlineColor.toRGBA() : 'black'

  // text-shadow 的宽度只能设置成1,大了会有四个影子
  const shadowWidth = outlineWidth && outlineWidth > 0 ? 1 : 0

  textDiv.id = id
  textDiv.className = 'three-label'
  textDiv.textContent = text
  textDiv.style.color = fillColor ? fillColor.toRGBA() : 'white'
  textDiv.style.fontSize = (fontSize || 12) + 'px'
  textDiv.style.backgroundColor = 'transparent'

  // 检测浏览器类型
  const isFirefox = navigator.userAgent.includes('Firefox')
  const isWebKit = 'WebkitAppearance' in document.documentElement.style

  // 根据不同浏览器应用样式
  if (isFirefox) {
    // Firefox: 使用 text-shadow  浅色效果不太好,像重影。黑色之类的深色效果还行。
    textDiv.style.textShadow = `${shadowWidth}px -${shadowWidth}px 0 ${shadowColor}, ${shadowWidth}px -${shadowWidth}px 0 ${shadowColor}, -${shadowWidth}px ${shadowWidth}px 0 ${shadowColor}, ${shadowWidth}px ${shadowWidth}px 0 ${shadowColor}`
  } else if (isWebKit) {
    // WebKit 内核浏览器: 使用 -webkit-text-stroke
    textDiv.style.webkitTextStroke = `${outlineWidth}px ${outlineColor.toHex()}` // 直接描边
    // 确保描边在文字填充下方(修复描边覆盖问题)
    textDiv.style.paintOrder = 'stroke fill'
  }
  // textDiv.style.opacity = '60%'
  if (pixelOffset) {
    textDiv.style.transform += `translate(${pixelOffset.x}px, ${pixelOffset.y}px)`
  }
  if (scaleByDistance) {
    textDiv.style.position = 'absolute'
    textDiv.style.transform += 'translate(-50%, -50%)' // 以元素中心为定位点
    textDiv.style.pointerEvents = 'none' // 防止点击穿透
  }
  const textLabel = new CSS2DObject(textDiv) 

  textLabel.userData.id = id
  textLabel.userData.scaleByDistance = scaleByDistance
  textLabel.position.set(position.x, position.y, position.z)
  // textLabel.center.set(0, 1);
  // textLabel.layers.set(0)
  return textLabel
}
  

使用z-index实现文字描边

描边宽度可控、效果好且稳定。
在这里插入图片描述

function createTextWithStroke (text: string, options: any = {}) {
 const {
   fontSize = 16,
   fillColor = TColor.fromHex('#fff'),
   outlineColor = TColor.fromHex('#f00'),
   outlineWidth = 2,
   fontFamily = 'Arial',
   pixelOffset,
   scaleByDistance,
 } = options

 // 创建容器
 const wrapper = document.createElement('div')

 wrapper.style.position = 'relative'
 wrapper.style.display = 'inline-block'

 // 创建描边层
 const strokeLayer = document.createElement('div')

 strokeLayer.textContent = text
 strokeLayer.style.position = 'absolute'
 strokeLayer.style.left = '0'
 strokeLayer.style.top = '0'
 strokeLayer.style.webkitTextStroke = `${outlineWidth}px ${outlineColor.toHex()}`
 strokeLayer.style.zIndex = '-1'

 // 创建填充层
 const fillLayer = document.createElement('div')

 fillLayer.textContent = text
 fillLayer.style.color = fillColor.toHex();

 // 统一字体样式
 [strokeLayer, fillLayer].forEach((layer) => {
   layer.style.fontSize = `${fontSize}px`
   layer.style.fontFamily = fontFamily
   layer.style.whiteSpace = 'nowrap' // 防止文字换行

   // textDiv.style.opacity = '60%'
   if (pixelOffset) {
     layer.style.transform += `translate(${pixelOffset.x}px, ${pixelOffset.y}px)`
   }
   if (scaleByDistance) {
     layer.style.position = 'absolute'
     layer.style.transform += 'translate(-50%, -50%)' // 以元素中心为定位点
     layer.style.pointerEvents = 'none' // 防止点击穿透
   }
 })

 // 构建 DOM 结构
 wrapper.appendChild(strokeLayer)
 wrapper.appendChild(fillLayer)

 return wrapper
} 
function generateLabel (options: any) {
 const { id, position, text, scaleByDistance } = options
 const myText = createTextWithStroke(text, options)
 const textLabel = new CSS2DObject(myText)

 textLabel.userData.id = id
 textLabel.userData.scaleByDistance = scaleByDistance
 textLabel.position.set(position.x, position.y, position.z)

 return textLabel
}
 const textLabel = generateLabel(this.options)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值