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)