// coordinate 多边形数据
coordinate.forEach((rows:any) => {
const line = lineDraw(rows, outLineColor ?? ‘0xffffff’);
chinaLines.add(line);
});
});
positions = new Float32Array(linePinots.flat(1));
// 设置顶点
opacityGeometry.setAttribute(“position”, new BufferAttribute(positions, 3));
// 设置 粒子透明度为 0
opacitys = new Float32Array(positions.length).map(() => 0);
opacityGeometry.setAttribute(“aOpacity”, new BufferAttribute(opacitys, 1));
// 控制 颜色和粒子大小
const params = {
pointSize: 2.0,
pointColor: tintColor
}
const vertexShader = `
attribute float aOpacity;
uniform float uSize;
varying float vOpacity;
void main(){
gl_Position = projectionMatrixmodelViewMatrixvec4(position,1.0);
gl_PointSize = uSize;
vOpacity=aOpacity;
}
`
const fragmentShader = `
varying float vOpacity;
uniform vec3 uColor;
float invert(float n){
return 1.-n;
}
void main(){
if(vOpacity <=0.2){
discard;
}
vec2 uv=vec2(gl_PointCoord.x,invert(gl_PointCoord.y));
vec2 cUv=2.*uv-1.;
vec4 color=vec4(1./length(cUv));
color*=vOpacity;
color.rgb*=uColor;
gl_FragColor=color;
}
`
const material = new ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true, // 设置透明
uniforms: {
uSize: {
value: params.pointSize
},
uColor: {
value: new Color(params.pointColor)
}
}
})
const opacityPoints = new Points(opacityGeometry, material)
return {
chinaLines,
opacityPoints,
opacitys,
linePinots,
opacityGeometry
}
}
// let indexBol = true
/**
-
边框 图形绘制
-
@param polygon 多边形 点数组
-
@param color 材质颜色
-
*/
function lineDraw(polygon:any, color:ColorRepresentation) {
const lineGeometry = new BufferGeometry();
const pointsArray = new Array();
polygon.forEach((row:any) => {
const projectionRow = projection(row);
if (!projectionRow) {
return
}
let x = projectionRow[0]
let y = projectionRow[1]
// 创建三维点
pointsArray.push(new Vector3(x, -y, 0));
linePinots.push([x, -y, 0]);
});
// 放入多个点
lineGeometry.setFromPoints(pointsArray);
const lineMaterial = new LineBasicMaterial({
color: color,
});
return new Line(lineGeometry, lineMaterial);
}
export { countryLine };
全部代码: demo
geojson 版本我们需要将提供的经纬度坐标点转场成平面,各平台算法不同,投影失真情况不同,所以一些情况地图会失真无法重合。
我们刚才使用卡墨托投影转换,也会失真并且和echarts 地图轮廓对不上,所以想起其他方案。
我们利用svg路径来取点,UI提供的svg地图轮廓肯定是一致的。
设计思路:
-
加载svg 取所有的点
-
根绝点来创建threejs 亮光点
-
移动动画
核心代码:
import * as THREE from ‘three’;
import { initRender } from ‘./render’;
import { initScene } from ‘./scene’;
import { initCamera } from ‘./camera’;
// import { countryLine } from “./countryPolygon”;
import { SVGLoader } from ‘three/examples/jsm/loaders/SVGLoader.js’;
export interface OutLineConfig {
outline: boolean;
outlineColor?: THREE.ColorRepresentation;
tintColor: THREE.ColorRepresentation;
speed: number;
tintLength?: number;
tintPointSize?: number;
}
class MapOutline {
private parentDom: HTMLElement;
private width: number;
private height: number;
private renderer: THREE.WebGLRenderer;
private scene: THREE.Scene;
private camera: THREE.PerspectiveCamera;
private opacitys: Float32Array | null = null;
private linePinots: any[] = [];
private opacityGeometry: THREE.BufferGeometry | null = null;
private currentPos = 0;
public constructor(
containerId: string,
public config: OutLineConfig = { outline: false, speed: 3, tintColor: ‘#008792’ },
) {
this.parentDom = document.getElementById(containerId)!;
this.width = this.parentDom.offsetWidth;
this.height = this.parentDom.offsetHeight;
this.renderer = initRender(this.width, this.height);
this.parentDom?.appendChild(this.renderer.domElement);
this.scene = initScene();
this.camera = initCamera(this.width, this.height);
}
public render = () => {
const loader = new SVGLoader();
loader.load(‘./chinaLine.svg’, (data) => {
const paths = data.paths;
const group = new THREE.Group();
group.scale.multiplyScalar(0.34);
group.position.x = -117;
group.position.y = 90;
group.scale.y *= -1;
let allPoints: any[] = [];
let pointsMesh: THREE.Points | null = null;
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const strokeColor = path.userData?.style.stroke;
const material = new THREE.MeshBasicMaterial({
color: ‘red’,
opacity: path.userData?.style.strokeOpacity,
transparent: path.userData?.style.strokeOpacity < 1,
side: THREE.DoubleSide,
depthWrite: false,
});
for (let j = 0, jl = path.subPaths.length; j < jl; j++) {
const subPath = path.subPaths[j];
let subPoints = subPath.getPoints();
allPoints = allPoints.concat(subPoints);
const geometry = SVGLoader.pointsToStroke(subPath.getPoints(), path.userData?.style);
if (geometry) {
const mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
}
}
allPoints = allPoints.map((item) => {
item.z = 0;
return item;
});
for (const point of allPoints) {
this.linePinots.push(point.x * 0.34 - 117, -point.y * 0.34 + 90, point.z);
}
this.opacityGeometry = new THREE.BufferGeometry();
this.opacitys = new Float32Array(this.linePinots.length).map(() => 0);
this.opacityGeometry.setAttribute(‘position’, new THREE.Float32BufferAttribute(this.linePinots, 3));
this.opacityGeometry.setAttribute(‘aOpacity’, new THREE.BufferAttribute(this.opacitys, 1));
// 控制 颜色和粒子大小
const params = {
pointSize: 5.0,
pointColor: ‘DarkOrange’,
};
const vertexShader = `
attribute float aOpacity;
uniform float uSize;
varying float vOpacity;
void main(){
gl_Position = projectionMatrixmodelViewMatrixvec4(position,1.0);
gl_PointSize = uSize;
vOpacity=aOpacity;
}
`;
const fragmentShader = `
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。
课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
[外链图片转存中…(img-FQkeYpnt-1713234928492)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。