服务器网站路径问题,如何免费做网络推广,教育做的比较好的网站有哪些,山西专业制作网站实现思路
首先是需要用canvas绘制一个2D的热力图#xff0c;如果你还不会#xff0c;请看json绘制热力图。使用Threejs中的canvas贴图#xff0c;将贴图贴在PlaneGeometry平面上。使用着色器材质#xff0c;更具json中的数据让平面模型 拔地而起。使用Threejs内置的TWEEN如果你还不会请看json绘制热力图。使用Threejs中的canvas贴图将贴图贴在PlaneGeometry平面上。使用着色器材质更具json中的数据让平面模型 拔地而起。使用Threejs内置的TWEEN加上一个动画。
效果
效果如下 具体代码
具体实现效果代码
import * as THREE from three;
import * as TWEEN from three/examples/jsm/libs/tween.module.js;
import { OrbitControls } from three/addons/controls/OrbitControls.js
import * as d3geo from d3-geo
import trafficJSON from ../assets/json/traffic.jsonexport default (domId) {/* ------------------------------初始化三件套--------------------------------- */const dom document.getElementById(domId);const { innerHeight, innerWidth } windowconst scene new THREE.Scene();const camera new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000);camera.position.set(-25, 288, 342);camera.lookAt(scene.position);const renderer new THREE.WebGLRenderer({antialias: true,// 抗锯齿alpha: false,// 透明度powerPreference: high-performance,// 性能logarithmicDepthBuffer: true,// 深度缓冲})// renderer.setClearColor(0x000000, 0);// 设置背景色// renderer.clear();// 清除渲染器renderer.shadowMap.enabled true;// 开启阴影renderer.shadowMap.type THREE.PCFSoftShadowMap;// 阴影类型renderer.outputEncoding THREE.sRGBEncoding;// 输出编码renderer.toneMapping THREE.ACESFilmicToneMapping;// 色调映射renderer.toneMappingExposure 1;// 色调映射曝光renderer.physicallyCorrectLights true;// 物理正确灯光renderer.setPixelRatio(devicePixelRatio);// 设置像素比renderer.setSize(innerWidth, innerHeight);// 设置渲染器大小dom.appendChild(renderer.domElement);// 重置大小window.addEventListener(resize, () {const { innerHeight, innerWidth } windowcamera.aspect innerWidth / innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth, innerHeight);})/* ------------------------------初始化工具--------------------------------- */const controls new OrbitControls(camera, renderer.domElement) // 相机轨道控制器controls.enableDamping true // 是否开启阻尼controls.dampingFactor 0.05// 阻尼系数controls.panSpeed -1// 平移速度const axesHelper new THREE.AxesHelper(10);scene.add(axesHelper);/* ------------------------------正题--------------------------------- */let geoFun;// 地理投影函数let info {max: Number.MIN_SAFE_INTEGER,min: Number.MAX_SAFE_INTEGER,maxlng: Number.MIN_SAFE_INTEGER,minlng: Number.MAX_SAFE_INTEGER,maxlat: Number.MIN_SAFE_INTEGER,minlat: Number.MAX_SAFE_INTEGER,data: []};// 初始化地理投影const initGeo (size) {geoFun d3geo.geoMercator().scale(size || 100)}// 经纬度转像素坐标const latlng2px (pos) {if (pos[0] -180 pos[0] 180 pos[1] -90 pos[1] 90) {return geoFun(pos);}return pos;};// 创建颜色const createColors (option) {const canvas document.createElement(canvas);const ctx canvas.getContext(2d);canvas.width 256;canvas.height 1;const grad ctx.createLinearGradient(0, 0, canvas.width, canvas.height);for (let k in option.colors) {grad.addColorStop(k, option.colors[k]);}ctx.fillStyle grad;ctx.fillRect(0, 0, canvas.width, canvas.height);return ctx.getImageData(0, 0, canvas.width, 1).data;}// 绘制圆const drawCircle (ctx, option, item) {let { lng, lat, value } item;let x lng - option.minlng option.radius;let y lat - option.minlat option.radius;const grad ctx.createRadialGradient(x, y, 0, x, y, option.radius);grad.addColorStop(0.0, rgba(0,0,0,1));grad.addColorStop(1.0, rgba(0,0,0,0));ctx.fillStyle grad;ctx.beginPath();ctx.arc(x, y, option.radius, 0, 2 * Math.PI);ctx.closePath();ctx.globalAlpha (value - option.min) / option.size;ctx.fill();}// 创建热力图const createHeatmap (option) {const canvas document.createElement(canvas);canvas.width option.width;canvas.height option.height;const ctx canvas.getContext(2d);option.size option.max - option.min;option.data.forEach((item) {drawCircle(ctx, option, item);});const colorData createColors(option);const imageData ctx.getImageData(0, 0, canvas.width, canvas.height);for (let i 3; i imageData.data.length; i i 4) {let opacity imageData.data[i];let offset opacity * 4;//redimageData.data[i - 3] colorData[offset];//greenimageData.data[i - 2] colorData[offset 1];//blueimageData.data[i - 1] colorData[offset 2];}ctx.putImageData(imageData, 0, 0);return { canvas, option };}// 初始化const init () {initGeo(1000)// 处理数据trafficJSON.features.forEach((item) {let pos latlng2px(item.geometry.coordinates);// 经纬度转像素坐标let newitem {lng: pos[0],lat: pos[1],value: item.properties.avg}info.max Math.max(newitem.value, info.max);info.maxlng Math.max(newitem.lng, info.maxlng);info.maxlat Math.max(newitem.lat, info.maxlat);info.min Math.min(newitem.value, info.min);info.minlng Math.min(newitem.lng, info.minlng);info.minlat Math.min(newitem.lat, info.minlat);info.data.push(newitem);})info.size info.max - info.min;info.sizelng info.maxlng - info.minlng;info.sizelat info.maxlat - info.minlat;const radius 50;const { canvas, option } createHeatmap({width: info.sizelng radius * 2,height: info.sizelng radius * 2,colors: {0.1: #2A85B8,0.2: #16B0A9,0.3: #29CF6F,0.4: #5CE182,0.5: #7DF675,0.6: #FFF100,0.7: #FAA53F,1: #D04343},radius,...info})const map new THREE.CanvasTexture(canvas);map.wrapS THREE.RepeatWrapping;map.wrapT THREE.RepeatWrapping;// 创建平面const geometry new THREE.PlaneGeometry(option.width * 0.5,option.height * 0.5,500,500);const material new THREE.ShaderMaterial({transparent: true,side: THREE.DoubleSide,uniforms: {map: { value: map },uHeight: { value: 100 },uOpacity: { value: 2.0 }},vertexShader: uniform sampler2D map;uniform float uHeight;varying vec2 v_texcoord;void main(void){v_texcoord uv;float htexture2D(map, v_texcoord).a*uHeight;gl_Position projectionMatrix * modelViewMatrix * vec4( position.x,position.y,h, 1.0 );},fragmentShader: precision mediump float;uniform sampler2D map;uniform float uOpacity;varying vec2 v_texcoord;void main (void){vec4 color texture2D(map, v_texcoord);float acolor.a*uOpacity;gl_FragColor.rgb color.rgb;gl_FragColor.aa1.0?1.0:a;}});const plane new THREE.Mesh(geometry, material);plane.rotateX(-Math.PI * 0.5);scene.add(plane);const tween new TWEEN.Tween({ v: 0 }).to({ v: 100 }, 2000).onUpdate(obj {material.uniforms.uHeight.value obj.v;}).easing(TWEEN.Easing.Quadratic.InOut).start();TWEEN.add(tween);}init();/* ------------------------------动画函数--------------------------------- */const animation () {TWEEN.update();controls.update();// 如果不调用就会很卡renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
}