计算threejs背景颜色改变透明组件的深浅

一个没什么用的小功能,以后也不会用到了,花了两天的时间,快要删代码了记录一下

step 1: 获取背景平均像素值

x,y 为矩形左下角坐标

js 复制代码
getRGB (x, y, width, height) {
//先获取context
    let gl = ThreeGlobal_.renderer.getContext()
    const length = 4 * width * height
    let pixelsArray = new Uint8Array(length)
//重新渲染此帧避免获取到空值
    ThreeGlobal_.renderer.render(ThreeGlobal_.scene, ThreeGlobal_.default_camera)
 //笨笨地把全部像素拿出来了
    gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelsArray)
    let avg = [0, 0, 0, 0]
    for (var i = 0; i < length; i += 4) {
      avg[0] += pixelsArray[i + 0]
      avg[1] += pixelsArray[i + 1]
      avg[2] += pixelsArray[i + 2]
      avg[3] += pixelsArray[i + 3]
    }
    avg = avg.map(item => {
      return item / height / width
    })
    console.log('ohyeah', avg)
    return avg
  },

(题外话,以下代码是获取背景截图而不是获取平均值,与功能无关)

js 复制代码
  // 获取区域图像
  getImage (x, y, width, height) {
    let gl = ThreeGlobal_.renderer.getContext()
    var canvas = document.createElement('canvas')
    var ctx = canvas.getContext('2d')
    var imageData = ctx.createImageData(width, height)
    const length = 4 * width * height
    // const row = width * 4
    // const end = (height - 1) * row
    const arr = new Uint8Array(length)
    let pixelsArray = new Uint8Array(length)
    ThreeGlobal_.renderer.render(ThreeGlobal_.scene, ThreeGlobal_.default_camera)
    gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, arr)
    for (let i = 0; i < length; i += row) {
      let sub = new Uint8Array(row)
      sub = arr.subarray(i, i + row)
      pixelsArray.set(sub, end - i)
    }
    for (var i = 0; i < imageData.data.length; i += 4) {
      imageData.data[i + 0] = pixelsArray[i + 0]
      imageData.data[i + 1] = pixelsArray[i + 1]
      imageData.data[i + 2] = pixelsArray[i + 2]
      imageData.data[i + 3] = pixelsArray[i + 3]
    }
    ctx.putImageData(imageData, 0, 0)
    // 如果想要翻转图像的话,感谢网上大神的代码。因为是用不到的功能,没有用心写
    // function imageDataVRevert (sourceData, newData, flag) {
    //   if (flag) {
    //             for (var i = 0, h = lll; i < h; i++) {
    //     for (var j = 0, w = lll; j < w; j++) {
    //       newData.data[i * w * 4 + j * 4 + 0] =
    //         sourceData.data[(h - i - 1) * w * 4 + j * 4 + 0]
    //       newData.data[i * w * 4 + j * 4 + 1] =
    //         sourceData.data[(h - i - 1) * w * 4 + j * 4 + 1]
    //       newData.data[i * w * 4 + j * 4 + 2] =
    //         sourceData.data[(h - i - 1) * w * 4 + j * 4 + 2]
    //       newData.data[i * w * 4 + j * 4 + 3] =
    //         sourceData.data[(h - i - 1) * w * 4 + j * 4 + 3]
    //     }
    //   }
    //   console.log('newImgData1', imageData, newImgData, flag, newData)
    //   return newData
    //   } else {
    //     console.log('newImgData2', imageData, newImgData, flag, newData, sourceData)
    //     return sourceData
    //   }
    // }
    // var newImgData = ctx.createImageData(lll, lll)
    // newImgData = imageDataVRevert(imageData, newImgData, flag)
    // console.log('newImgData3', imageData, newImgData, flag)
    // ctx.putImageData(newImgData, 0, 0)
    // console.log('imageData, newImgData', imageData, newImgData, flag)
    const win = window.open()
    win.document.write('<iframe src="' + canvas.toDataURL('image/png') + '" frameborder="0" style="border:0; top:250px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>' + '<div>' + x + y + '</div>')
  },

刚刚扯远了,回到step2

step 2: 根据平均像素值设置透明度

因为重新渲染再计算平均值有点耗费时间,所以计算了一下代码用时

js 复制代码
 changeAlphaColor () {
      const startTime = new Date()
      // 我的组件宽850px从右开始
      let w = 850
      let x = ThreeGlobal_.width - w
      let h = ThreeGlobal_.height
      let avg = SceneCommon.getRGB(x, 0, w, h)
    let alpha = ((avg[0] + avg[1] + avg[2]) * avg[3] / 255 / 255 / 3)
    // 透明度根据背景颜色改变,随手写的让他在[0.3,1]之间波动
    let alpha1 = 0.3 + alpha * 7 / 10
    // console.log('放到组件里alpha ', alpha1)
    //此处是重点,直接加样式表
    //在less里添加 @compAlpha:var(--compAlpha);
    //background: rgba(0,0,0,@compAlpha);
    document.documentElement.style.setProperty('--compAlpha', alpha1)
    //滚动样式修改用第一种方法无效
    let alpha2 = 1 - alpha1
    var cssStyle = `.ant-table-fixed-header > .ant-table-content > .ant-table-scroll > .ant-table-body::-webkit-scrollbar-thumb{background: rgba(255,255,255,${alpha2}) !important;}`
    const style = document.createElement('style')
    style.appendChild(document.createTextNode(cssStyle))
    document.head.appendChild(style)

  // // 记录结束时间
  const endTime = new Date()

  // // 计算执行时间(以毫秒为单位)
  const executionTime = endTime - startTime
  
  // // 输出执行时间
  console.log(`代码执行时间:${executionTime} 毫秒`)
    },

(继续题外话,当时没想通,想用颜色叠加代码,该透还得透,以下代码没有必要)

js 复制代码
    //colorT前景,colorB后景
    colorAddition (colorT, colorB) {
      let finalColor = []
      // 3为透明度
      finalColor[3] = colorT[3] + colorB[3] * (1 - colorT[3])
      for (let i = 0; i < 3; i++) {
        finalColor[i] = (colorT[i] * colorT[3] +
         colorB[i] * colorB[3] * (1 - colorT[3])) / finalColor[3]
      }
      return finalColor
    },

总结

第一种:样式修改方式

  1. alpha1 为变量
  2. js style.setProperty
js 复制代码
document.documentElement.style.setProperty('--compAlpha', alpha1) 
  1. less var(--compAlpha)
less 复制代码
 @compAlpha:var(--compAlpha);
    //background: rgba(0,0,0,@compAlpha);

第二种:滚动样式修改方式

  1. alpha2 为变量
  2. js createTextNode
js 复制代码
var cssStyle = `.ant-table-fixed-header > .ant-table-content > .ant-table-scroll > .ant-table-body::-webkit-scrollbar-thumb{background: rgba(255,255,255,${alpha2}) !important;}`
    const style = document.createElement('style')
    style.appendChild(document.createTextNode(cssStyle))
    document.head.appendChild(style)

ps:刚入职几个月的萌新,没人检查代码随便乱写,糊弄外行领导,轻喷|・ω・)

相关推荐
天涯学馆2 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF2 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi2 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi2 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript
积水成江3 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
Z3r4y3 小时前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
人生の三重奏3 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_3 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
老华带你飞3 小时前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计
qbbmnnnnnn4 小时前
【WebGis开发 - Cesium】如何确保Cesium场景加载完毕
前端·javascript·vue.js·gis·cesium·webgis·三维可视化开发