diff --git a/examples/demos/line/arrow-debug.ts b/examples/demos/line/arrow-debug.ts new file mode 100644 index 00000000000..8988ea38363 --- /dev/null +++ b/examples/demos/line/arrow-debug.ts @@ -0,0 +1,121 @@ +import { LineLayer, Source } from '@antv/l7'; +import type { TestCase } from '../../types'; +import { CaseScene } from '../../utils'; + +/** + * Arrow Line Demo + * + * 该示例演示如何在 L7 中为线图层添加箭头效果,常用于导航、路径方向标识。 + * + * 支持的箭头参数: + * - enable: 是否显示箭头 + * - spacing: 箭头间距(像素) + * - width: 箭头宽度(像素) + * - length: 箭头长度(像素) + * - strokeWidth: 箭头线条宽度(像素) + * - color: 箭头颜色(支持 CSS 色值) + * + * 箭头为 V 形轮廓,非实心三角,叠加在线本身之上。 + * 线和箭头可分别设置颜色,实现如“蓝色线+黄色箭头”效果。 + * + * 示例配置: + * arrow: { + * enable: true, + * spacing: 80, + * width: 30, + * length: 40, + * strokeWidth: 4, + * color: '#FFFF00', + * } + */ + +export const arrowDebug: TestCase = async (options) => { + const scene = await CaseScene({ + ...options, + mapConfig: { + style: 'dark', + center: [120, 30], + zoom: 10, + }, + }); + + console.log('=== Arrow Debug Demo Started ==='); + + // 一条简单的水平线用于测试 + const simpleLineData = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: { name: 'test' }, + geometry: { + type: 'LineString', + coordinates: [ + [119.9, 30], + [120.1, 30], + ], + }, + }, + ], + }; + + const arrowConfig = { + enable: true, + spacing: 15, // 间距 (像素) + width: 15, // 宽度 (像素) + length: 3, // 长度 (像素) + strokeWidth: 4, // 箭头线条宽度 (像素) + color: 'rgba(255, 94, 0, 1)', // 黄色箭头 + }; + + console.log('Creating line layer with arrow config:', arrowConfig); + + // 蓝色线,带黄色箭头 + const lineLayer = new LineLayer({ name: 'debug_arrow' }) + .source(new Source(simpleLineData)) + .shape('line') + .size(10) // 线宽 10px + .color('#0000FF') // 蓝色 + .style({ + arrow: arrowConfig, + }); + + console.log('Line layer created, adding to scene...'); + scene.addLayer(lineLayer); + console.log('Line layer added to scene'); + + // 添加一条不带箭头的对照线 - 青色 + const normalLine = new LineLayer({ name: 'normal_line' }) + .source( + new Source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + type: 'LineString', + coordinates: [ + [119.9, 30.05], + [120.1, 30.05], + ], + }, + }, + ], + }), + ) + .shape('line') + .size(8) + .color('#00FFFF'); // 改为青色对照线,不带箭头 + + scene.addLayer(normalLine); + console.log('Normal line (without arrows) added for comparison - cyan color'); + + // 延迟检查图层配置 + setTimeout(() => { + const config = lineLayer.getLayerConfig(); + console.log('Layer config after add:', config); + console.log('Arrow config from layer:', (config as any).arrow); + }, 1000); + + return scene; +}; diff --git a/examples/demos/line/arrow.ts b/examples/demos/line/arrow.ts new file mode 100644 index 00000000000..b8d8f4db829 --- /dev/null +++ b/examples/demos/line/arrow.ts @@ -0,0 +1,130 @@ +import { LineLayer, Source } from '@antv/l7'; +import type { TestCase } from '../../types'; +import { CaseScene } from '../../utils'; + +export const arrow: TestCase = async (options) => { + const scene = await CaseScene({ + ...options, + mapConfig: { + style: 'light', + center: [120.15, 30.25], + zoom: 13, + }, + }); + + // 模拟道路路径数据 + const roadData = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: { + name: '主干道', + }, + geometry: { + type: 'LineString', + coordinates: [ + [120.1, 30.2], + [120.12, 30.22], + [120.15, 30.24], + [120.18, 30.26], + [120.2, 30.28], + ], + }, + }, + { + type: 'Feature', + properties: { + name: '支路', + }, + geometry: { + type: 'LineString', + coordinates: [ + [120.1, 30.28], + [120.12, 30.26], + [120.14, 30.24], + [120.16, 30.22], + ], + }, + }, + { + type: 'Feature', + properties: { + name: '环形路', + }, + geometry: { + type: 'LineString', + coordinates: [ + [120.18, 30.2], + [120.2, 30.21], + [120.21, 30.23], + [120.2, 30.25], + [120.18, 30.26], + [120.16, 30.25], + [120.15, 30.23], + [120.16, 30.21], + [120.18, 30.2], + ], + }, + }, + ], + }; + + const source = new Source(roadData); + + // 创建带箭头的线图层 - 蓝色线条 + const lineLayer = new LineLayer({ name: 'arrow_line' }) + .source(source) + .shape('line') + .size(6) + .color('#1890ff') + .style({ + arrow: { + enable: true, + spacing: 30, // 间距 (像素) + width: 10, // 宽度 (像素) + length: 5, // 长度 (像素) + strokeWidth: 5, + color: 'rgba(255, 94, 0, 1)', // 黄色箭头 + }, + }); + + scene.addLayer(lineLayer); + + // 添加一个白色箭头的测试图层 + const whiteArrowLayer = new LineLayer({ name: 'white_arrow_line' }) + .source( + new Source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + type: 'LineString', + coordinates: [ + [120.1, 30.3], + [120.15, 30.3], + [120.2, 30.3], + ], + }, + }, + ], + }), + ) + .shape('line') + .size(6) + .color('red') + .style({ + arrow: { + enable: true, + spacing: 30, // 间距 (像素) + width: 10, // 宽度 (像素) + length: 5, // 长度 (像素) + strokeWidth: 5, + }, + }); + + scene.addLayer(whiteArrowLayer); + + return scene; +}; diff --git a/examples/demos/line/index.ts b/examples/demos/line/index.ts index baa3364075f..10d542a4629 100644 --- a/examples/demos/line/index.ts +++ b/examples/demos/line/index.ts @@ -1,5 +1,7 @@ export { arc } from './arc'; export { arc3D } from './arc-3d'; +export { arrow } from './arrow'; +export { arrowDebug } from './arrow-debug'; export { dash } from './dash'; export { flow } from './flow'; export { greatcircle } from './greatcircle'; diff --git a/examples/demos/polygon/fill_china.ts b/examples/demos/polygon/fill_china.ts index b41d512e321..faf5030755a 100644 --- a/examples/demos/polygon/fill_china.ts +++ b/examples/demos/polygon/fill_china.ts @@ -39,20 +39,6 @@ export const fillChina: TestCase = async (options) => { } return false; }); - - const color = [ - '#a50026', - '#d73027', - '#f46d43', - '#fdae61', - '#fee090', - '#ffffbf', - '#e0f3f8', - '#abd9e9', - '#74add1', - '#4575b4', - '#313695', - ]; // 行政区划填充色 const fillLayer = new PolygonLayer({ autoFit: true, diff --git a/packages/component/src/control/baseControl/control.ts b/packages/component/src/control/baseControl/control.ts index 44053520006..cbfbcb0f75e 100644 --- a/packages/component/src/control/baseControl/control.ts +++ b/packages/component/src/control/baseControl/control.ts @@ -178,7 +178,7 @@ export default class Control /** * 获取默认构造器参数 */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getDefault(option?: Partial): O { // tslint:disable-next-line:no-object-literal-type-assertion return { diff --git a/packages/component/src/control/baseControl/popperControl.ts b/packages/component/src/control/baseControl/popperControl.ts index 8e349ba1c1e..505bf91a1d8 100644 --- a/packages/component/src/control/baseControl/popperControl.ts +++ b/packages/component/src/control/baseControl/popperControl.ts @@ -51,7 +51,7 @@ export default class PopperControl< */ public getDefault(option?: Partial): O { const defaultOption = super.getDefault(option); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const position = option?.position ?? defaultOption.position!; return { ...super.getDefault(option), @@ -72,10 +72,9 @@ export default class PopperControl< public initPopper() { const { popperClassName, popperPlacement, popperTrigger } = this.controlOption; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const popperContainer = this.mapsService.getMapContainer()!; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.popper = new Popper(this.button!, { className: popperClassName, placement: popperPlacement, diff --git a/packages/component/src/control/fullscreen.ts b/packages/component/src/control/fullscreen.ts index 508746fedb8..dc52c185d41 100644 --- a/packages/component/src/control/fullscreen.ts +++ b/packages/component/src/control/fullscreen.ts @@ -44,7 +44,7 @@ export default class Fullscreen extends ButtonControl public onAdd(): HTMLElement { const button = super.onAdd(); button.addEventListener('click', this.onClick); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.mapContainer = DOM.getContainer(this.scene.getSceneConfig().id!); this.mapContainer.addEventListener('fullscreenchange', this.onFullscreenChange); return button; diff --git a/packages/component/src/utils/screenfull.ts b/packages/component/src/utils/screenfull.ts index 1e5b2038a28..73b9c1e8fa3 100644 --- a/packages/component/src/utils/screenfull.ts +++ b/packages/component/src/utils/screenfull.ts @@ -73,7 +73,6 @@ const eventNameMap = { }; let screenfull: any = { - // eslint-disable-next-line default-param-last request(element = document.documentElement, options) { return new Promise((resolve, reject) => { const onFullScreenEntered = () => { diff --git a/packages/core/src/services/component/IMarkerService.ts b/packages/core/src/services/component/IMarkerService.ts index 97301d09071..0ca60064c6f 100644 --- a/packages/core/src/services/component/IMarkerService.ts +++ b/packages/core/src/services/component/IMarkerService.ts @@ -41,6 +41,10 @@ export interface IMarker { closePopup(): this; setElement(el: HTMLElement): this; getMarkerLayerContainerSize: () => IMarkerContainerAndBounds | void; + /** + * Update marker position based on current map state. + */ + update(): void; /** * Hide the marker visually without removing it from the layer/data. */ diff --git a/packages/core/src/services/component/MarkerService.ts b/packages/core/src/services/component/MarkerService.ts index ddb53b5f2d8..7255d969842 100644 --- a/packages/core/src/services/component/MarkerService.ts +++ b/packages/core/src/services/component/MarkerService.ts @@ -10,6 +10,7 @@ export default class MarkerService implements IMarkerService { private markerLayers: IMarkerLayer[] = []; private unAddMarkers: IMarker[] = []; private unAddMarkerLayers: IMarkerLayer[] = []; + private mapEventsRegistered: boolean = false; public addMarkerLayer(markerLayer: IMarkerLayer): void { if (this.mapsService.map && this.mapsService.getMarkerContainer()) { @@ -33,6 +34,7 @@ export default class MarkerService implements IMarkerService { if (this.mapsService.map && this.mapsService.getMarkerContainer()) { this.markers.push(marker); marker.addTo(this.scene); + this.registerMapEvents(); } else { this.unAddMarkers.push(marker); } @@ -44,6 +46,7 @@ export default class MarkerService implements IMarkerService { this.markers.push(marker); }); this.unAddMarkers = []; + this.registerMapEvents(); } public addMarkerLayers(): void { @@ -61,6 +64,10 @@ export default class MarkerService implements IMarkerService { if (markerIndex > -1) { this.markers.splice(markerIndex, 1); } + // 如果所有 marker 都被移除,注销地图事件 + if (this.markers.length === 0) { + this.unregisterMapEvents(); + } } public removeAllMarkers(): void { @@ -71,7 +78,9 @@ export default class MarkerService implements IMarkerService { this.scene = scene; this.mapsService = scene.mapService; } + public destroy(): void { + this.unregisterMapEvents(); this.markers.forEach((marker: IMarker) => { marker.remove(); }); @@ -82,6 +91,33 @@ export default class MarkerService implements IMarkerService { this.markerLayers = []; } + private updateAllMarkers = () => { + this.markers.forEach((marker: IMarker) => { + marker.update(); + }); + }; + + private registerMapEvents(): void { + if (this.mapEventsRegistered || !this.mapsService) { + return; + } + this.mapEventsRegistered = true; + // 监听地图的相机变化事件(兼容不同底图) + // camerachange: 适用于高德1.x、mapbox等 + // viewchange: 适用于高德2.0 + this.mapsService.on('camerachange', this.updateAllMarkers); + this.mapsService.on('viewchange', this.updateAllMarkers); + } + + private unregisterMapEvents(): void { + if (!this.mapEventsRegistered || !this.mapsService) { + return; + } + this.mapEventsRegistered = false; + this.mapsService.off('camerachange', this.updateAllMarkers); + this.mapsService.off('viewchange', this.updateAllMarkers); + } + private removeMakerLayerMarker(layer: IMarkerLayer) { layer.destroy(); } diff --git a/packages/core/src/services/layer/IStyleAttributeService.ts b/packages/core/src/services/layer/IStyleAttributeService.ts index c94c12a6689..1e44ec7a5bf 100644 --- a/packages/core/src/services/layer/IStyleAttributeService.ts +++ b/packages/core/src/services/layer/IStyleAttributeService.ts @@ -95,8 +95,10 @@ export interface IEncodeFeature { [key: string]: any; } -export interface IVertexAttributeDescriptor - extends Omit { +export interface IVertexAttributeDescriptor extends Omit< + IAttributeInitializationOptions, + 'buffer' +> { /** * attribute name in vertex shader */ diff --git a/packages/core/src/services/renderer/IModel.ts b/packages/core/src/services/renderer/IModel.ts index 8d0c9f6d3d8..8de9016687c 100644 --- a/packages/core/src/services/renderer/IModel.ts +++ b/packages/core/src/services/renderer/IModel.ts @@ -56,7 +56,7 @@ type stencilOp = | gl.DECR | gl.INCR_WRAP | gl.DECR_WRAP; -// eslint-disable-next-line @typescript-eslint/no-unused-vars + type BlendingFunctionCombined = Partial<{ src: | gl.ZERO diff --git a/packages/core/src/services/renderer/passes/BaseNormalPass.ts b/packages/core/src/services/renderer/passes/BaseNormalPass.ts index bd2f3d0514b..be82bd88060 100644 --- a/packages/core/src/services/renderer/passes/BaseNormalPass.ts +++ b/packages/core/src/services/renderer/passes/BaseNormalPass.ts @@ -10,9 +10,9 @@ import type { IRendererService } from '../IRendererService'; /** * 常规 Pass 基类 */ -export default class BaseNormalPass - implements IPass -{ +export default class BaseNormalPass< + InitializationOptions = {}, +> implements IPass { protected shaderModuleService: IShaderModuleService; protected rendererService: IRendererService; @@ -41,7 +41,6 @@ export default class BaseNormalPass this.shaderModuleService = layer.getContainer().shaderModuleService; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars public render(layer: ILayer) { // } diff --git a/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts b/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts index 2036f662a8e..f4bcdbc2978 100644 --- a/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts +++ b/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts @@ -17,9 +17,9 @@ const { camelCase, isNil, upperFirst } = lodashUtil; * * 约定使用 u_Texture 传递渲染纹理。 */ -export default class BasePostProcessingPass - implements IPostProcessingPass -{ +export default class BasePostProcessingPass< + InitializationOptions = {}, +> implements IPostProcessingPass { protected shaderModuleService: IShaderModuleService; protected rendererService: IRendererService; diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index 6de52d70622..47439436eb0 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -1380,7 +1380,7 @@ export default class BaseLayer * 继承空方法 * @param time */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public setEarthTime(time: number) { console.warn('empty fn'); } diff --git a/packages/layers/src/core/BaseModel.ts b/packages/layers/src/core/BaseModel.ts index a416b977773..19b7803d4c1 100644 --- a/packages/layers/src/core/BaseModel.ts +++ b/packages/layers/src/core/BaseModel.ts @@ -58,7 +58,6 @@ type AttributeLayoutLocationType = typeof COMMON_ATTRIBUTE_LOCATION & Record implements ILayerModel { public triangulation: Triangulation; public uniformBuffers: IBuffer[] = []; @@ -190,15 +189,15 @@ export default class BaseModel implements ILayerMod public async needUpdate(): Promise { return false; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async buildModels(): Promise { throw new Error('Method not implemented.'); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async initModels(): Promise { throw new Error('Method not implemented.'); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public clearModels(refresh = true) { return; } @@ -211,7 +210,7 @@ export default class BaseModel implements ILayerMod throw new Error('Method not implemented.'); } public prerender(): void {} - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public render(renderOptions?: Partial): void { throw new Error('Method not implemented.'); } diff --git a/packages/layers/src/core/interface.ts b/packages/layers/src/core/interface.ts index 41f76e624c6..042d0969374 100644 --- a/packages/layers/src/core/interface.ts +++ b/packages/layers/src/core/interface.ts @@ -80,6 +80,16 @@ export interface ILineLayerStyleOptions extends IBaseLayerStyleOptions { symbol?: ILineSymbol; + // 箭头配置 + arrow?: { + enable?: boolean; // 是否启用箭头 + spacing?: number; // 箭头间距(像素单位) + width?: number; // 箭头宽度(像素单位) + length?: number; // 箭头长度(像素单位) + strokeWidth?: number; // 箭头线条宽度(像素单位,默认 2) + color?: string; // 箭头颜色,默认白色 + }; + rampColors?: IColorRamp; featureId?: string; sourceLayer?: string; diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index 3204f88f193..ef564ccc84d 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -16,6 +16,7 @@ import { primitiveSphere, } from '../earth/utils'; import ExtrudePolyline from '../utils/extrude_polyline'; +import type { ILineLayerStyleOptions } from './interface'; import type { IPosition, ShapeType2D, ShapeType3D } from './shape/Path'; import { geometryShape } from './shape/Path'; import type { IExtrudeGeomety } from './shape/extrude'; @@ -86,13 +87,13 @@ export function PointImageTriangulation(feature: IEncodeFeature) { /** * 线三角化 * @param feature 映射feature + * @param styleOption 样式配置(从 buildLayerModel 传入) */ -export function LineTriangulation(feature: IEncodeFeature) { +export function LineTriangulation( + feature: IEncodeFeature, + styleOption?: Partial, +) { const { coordinates } = feature; - // let path = coordinates as number[][][] | number[][]; - // if (!Array.isArray(path[0][0])) { - // path = [coordinates] as number[][][]; - // } const line = new ExtrudePolyline({ dash: true, @@ -108,6 +109,7 @@ export function LineTriangulation(feature: IEncodeFeature) { }); const linebuffer = line.complex; + return { vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ] indices: linebuffer.indices, diff --git a/packages/layers/src/line/models/line.ts b/packages/layers/src/line/models/line.ts index d70db29c773..ab79f8cfc28 100644 --- a/packages/layers/src/line/models/line.ts +++ b/packages/layers/src/line/models/line.ts @@ -51,6 +51,7 @@ export default class LineModel extends BaseModel { heightfixed = false, linearDir = LinearDir.VERTICAL, // 默认纵向 blur = [1, 1, 1, 0], + arrow, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; let u_dash_array = dashArray; if (lineType !== 'dash') { @@ -78,6 +79,7 @@ export default class LineModel extends BaseModel { u_blur: blur, u_sourceColor: sourceColorArr, u_targetColor: targetColorArr, + u_arrow_color: arrow?.color ? rgb2arr(arrow.color) : [1, 1, 1, 1], // vec4 必须紧跟其他 vec4 u_textSize: [1024, this.iconService.canvasHeight || 128], u_icon_step: iconStep, // 是否固定高度 @@ -92,9 +94,16 @@ export default class LineModel extends BaseModel { u_linearDir: linearDir === LinearDir.VERTICAL ? 1.0 : 0.0, u_linearColor: useLinearColor, u_time: this.layer.getLayerAnimateTime() || 0, + // 箭头参数 + u_arrow: arrow?.enable ? 1.0 : 0.0, + u_arrow_spacing: arrow?.spacing || 50, // 默认间距 50px + u_arrow_width: arrow?.width || 15, // 箭头宽度 15px + u_arrow_height: arrow?.length || 20, // 箭头长度 20px + u_arrow_strokeWidth: arrow?.strokeWidth || 2, // 箭头线条宽度 2px }; const commonBufferInfo = this.getUniformsBufferInfo(commonOptions); + return commonBufferInfo; } // public getAnimateUniforms(): IModelUniform { diff --git a/packages/layers/src/line/shaders/line/line_frag.glsl b/packages/layers/src/line/shaders/line/line_frag.glsl index fe9c2789aab..6dab1cbd510 100644 --- a/packages/layers/src/line/shaders/line/line_frag.glsl +++ b/packages/layers/src/line/shaders/line/line_frag.glsl @@ -9,6 +9,7 @@ layout(std140) uniform commonUniorm { vec4 u_blur; vec4 u_sourceColor; vec4 u_targetColor; + vec4 u_arrow_color; vec2 u_textSize; float u_icon_step: 100; float u_heightfixed: 0.0; @@ -20,6 +21,11 @@ layout(std140) uniform commonUniorm { float u_linearDir: 1.0; float u_linearColor: 0; float u_time; + float u_arrow: 0.0; + float u_arrow_spacing: 20.0; + float u_arrow_width: 1.0; + float u_arrow_height: 1.0; + float u_arrow_strokeWidth: 2.0; }; in vec4 v_color; @@ -32,6 +38,7 @@ in vec4 v_texture_data; out vec4 outputColor; #pragma include "picking" +#pragma include "projection" // [animate, duration, interval, trailLength], void main() { @@ -118,5 +125,57 @@ void main() { outputColor.a *= mix(u_blur.g, u_blur.b, (blurV - 0.5)/0.5); } + // 绘制箭头 + if(u_arrow > 0.0) { + // 使用地理距离来计算箭头分布 + float lineDistance = v_texture_data.g; + float texV = v_texture_data.a; // [0, 1] + + // 计算像素到地理单位的转换系数 (从 zoom level 推导) + float pixelToGeo = pow(2.0, 20.0 - u_Zoom); + + // 箭头参数 (将像素转换为地理单位) + float spacing = u_arrow_spacing * pixelToGeo; + float arrowLength = u_arrow_height * pixelToGeo; + float arrowWidthPx = u_arrow_width; + + // 当前距离在周期内的位置 + float distInCycle = mod(lineDistance, spacing); + + // 如果在箭头长度范围内 + if(distInCycle < arrowLength) { + // 归一化 U 坐标 [0, 1] (从箭头尾部到头部) + float u = distInCycle / arrowLength; + + // 计算当前像素偏离中心的距离 + // texV 在 [0, 1] 范围,中心是 0.5 + // 我们需要将其转换为像素偏移 + // 方法: 利用箭头宽度作为参考 + // 假设箭头宽度对应 texV 的某个范围 + float vOffset = (texV - 0.5) * 2.0; // 归一化到 [-1, 1] + + // 箭头形状计算: > 形 + // 宽度随 u 线性减小: u=0 -> width=max, u=1 -> width=0 + float halfWidthAtU = (1.0 - u) * 0.5; // [0, 0.5] + + // 箭头线条粗细 (归一化单位,相对于箭头宽度) + float strokeWidth = u_arrow_strokeWidth / max(arrowWidthPx, 1.0); + + // 判断是否在箭头线条上 + float distToEdge = abs(abs(vOffset) - halfWidthAtU); + + // 使用 smoothstep 进行抗锯齿 + float alpha = smoothstep(strokeWidth * 0.5 + 0.01, strokeWidth * 0.5 - 0.01, distToEdge); + + if(alpha > 0.0) { + // DEBUG: 先测试固定颜色是否工作 + // vec4 arrowColor = vec4(1.0, 1.0, 0.0, 1.0); // 强制黄色 + // 使用 uniform 的颜色 + vec4 arrowColor = vec4(u_arrow_color.rgb, u_arrow_color.a * alpha); + outputColor = mix(outputColor, arrowColor, alpha); + } + } + } + outputColor = filterColor(outputColor); } diff --git a/packages/layers/src/line/shaders/line/line_vert.glsl b/packages/layers/src/line/shaders/line/line_vert.glsl index ac2d4116638..ee1b8c28c79 100644 --- a/packages/layers/src/line/shaders/line/line_vert.glsl +++ b/packages/layers/src/line/shaders/line/line_vert.glsl @@ -14,6 +14,7 @@ layout(std140) uniform commonUniorm { vec4 u_blur; vec4 u_sourceColor; vec4 u_targetColor; + vec4 u_arrow_color; vec2 u_textSize; float u_icon_step: 100; float u_heightfixed: 0.0; @@ -25,6 +26,11 @@ layout(std140) uniform commonUniorm { float u_linearDir: 1.0; float u_linearColor: 0; float u_time; + float u_arrow: 0.0; + float u_arrow_spacing: 20.0; + float u_arrow_width: 1.0; + float u_arrow_height: 1.0; + float u_arrow_strokeWidth: 2.0; }; out vec4 v_color; @@ -44,8 +50,12 @@ void main() { float a_Miter = a_DistanceAndIndexAndMiter.z; vec3 a_Normal = a_Normal_Total_Distance.xyz; float a_Total_Distance = a_Normal_Total_Distance.w; + + // Pixel to Geo conversion factor + float pixelToGeo = pow(2.0, 20.0 - u_Zoom); + //dash输出 - v_dash_array = pow(2.0, 20.0 - u_Zoom) * u_dash_array / a_Total_Distance; + v_dash_array = pixelToGeo * u_dash_array / a_Total_Distance; v_d_distance_ratio = a_DistanceAndIndex.x / a_Total_Distance; // cal style mapping - 数据纹理映射部分的计算 @@ -56,7 +66,7 @@ void main() { v_color = a_Color; v_color.a *= opacity; v_stroke = stroke; - + vec3 size = a_Miter * setPickingSize(a_Size.x) * a_Normal; vec2 offset = project_pixel(size.xy); @@ -66,9 +76,10 @@ void main() { float lineOffsetWidth = length(offset + offset * sign(a_Miter)); // 线横向偏移的距离(向两侧偏移的和) float linePixelSize = project_pixel(a_Size.x) * 2.0; // 定点位置偏移,按地图等级缩放后的距离 单侧 * 2 - float texV = lineOffsetWidth / linePixelSize; // 线图层贴图部分的 v 坐标值 + float texV = lineOffsetWidth / linePixelSize; v_texture_data = vec4(currentLinePointRatio, lineDistance, d_texPixelLen, texV); + // 设置数据集的参数 vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0), a_Position64Low); diff --git a/packages/layers/src/plugins/FeatureScalePlugin.ts b/packages/layers/src/plugins/FeatureScalePlugin.ts index 07e17a27631..a58e1fd1c74 100644 --- a/packages/layers/src/plugins/FeatureScalePlugin.ts +++ b/packages/layers/src/plugins/FeatureScalePlugin.ts @@ -99,7 +99,7 @@ export default class FeatureScalePlugin implements ILayerPlugin { if (attribute.scale) { // 创建Scale const attributeScale = attribute.scale; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const fieldValue = attribute!.scale!.field; attributeScale.names = this.parseFields(isNil(fieldValue) ? [] : fieldValue); const scales: IStyleScale[] = []; @@ -213,7 +213,7 @@ export default class FeatureScalePlugin implements ILayerPlugin { } return styleScale; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const firstValue = data!.find((d) => !isNil(d[field]))?.[field]; // 常量 Scale if (this.isNumber(field) || (isNil(firstValue) && !scaleOption)) { diff --git a/packages/layers/src/tile/core/BaseLayer.ts b/packages/layers/src/tile/core/BaseLayer.ts index 71a9bd5f92f..820ee1525b0 100644 --- a/packages/layers/src/tile/core/BaseLayer.ts +++ b/packages/layers/src/tile/core/BaseLayer.ts @@ -113,7 +113,7 @@ export default class BaseTileLayer { private bindTilesetEvent() { // 瓦片数据加载成功 - // eslint-disable-next-line @typescript-eslint/no-unused-vars + this.tilesetManager.on('tile-loaded', (tile: SourceTile) => { // 将事件抛出,图层上可以监听使用 }); @@ -125,7 +125,7 @@ export default class BaseTileLayer { }); // 瓦片数据加载失败 - // eslint-disable-next-line @typescript-eslint/no-unused-vars + this.tilesetManager.on('tile-error', (error, tile: SourceTile) => { // 将事件抛出,图层上可以监听使用 this.tileError(error); @@ -160,7 +160,6 @@ export default class BaseTileLayer { // 防抖操作 public viewchange = debounce(this.mapchange, 24); - // eslint-disable-next-line @typescript-eslint/no-unused-vars public tileLoaded(tile: SourceTile) { // } @@ -227,7 +226,6 @@ export default class BaseTileLayer { } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars public setPickState(layers: ILayer[]) { return; } diff --git a/packages/layers/src/tile/service/TilePickService.ts b/packages/layers/src/tile/service/TilePickService.ts index b0ed0ec0b33..e32a3ad490a 100644 --- a/packages/layers/src/tile/service/TilePickService.ts +++ b/packages/layers/src/tile/service/TilePickService.ts @@ -127,7 +127,7 @@ export class TilePickService implements ITilePickService { } // Tip: for interface define - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public pickRasterLayer() { return false; } diff --git a/packages/layers/src/tile/tile/Tile.ts b/packages/layers/src/tile/tile/Tile.ts index b62615278ac..c8c5691fd34 100644 --- a/packages/layers/src/tile/tile/Tile.ts +++ b/packages/layers/src/tile/tile/Tile.ts @@ -33,7 +33,6 @@ export default abstract class Tile extends EventEmitter implements ITile { return this.layers; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars public styleUpdate(...arg: any) { return; } @@ -147,7 +146,7 @@ export default abstract class Tile extends EventEmitter implements ITile { public getMainLayer(): ILayer | undefined { return this.layers[0]; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getFeatures(sourceLayer: string | undefined): any[] { return []; } @@ -157,7 +156,7 @@ export default abstract class Tile extends EventEmitter implements ITile { * @param id * @returns */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getFeatureById(id: number): any[] { return []; } diff --git a/packages/layers/src/utils/extrude_polyline.ts b/packages/layers/src/utils/extrude_polyline.ts index c4213155073..a7ed0af898b 100644 --- a/packages/layers/src/utils/extrude_polyline.ts +++ b/packages/layers/src/utils/extrude_polyline.ts @@ -2,7 +2,7 @@ import { aProjectFlat } from '@antv/l7-utils'; import type { vec3 } from 'gl-matrix'; import { vec2 } from 'gl-matrix'; const tmp = vec2.create(); -// eslint-disable-next-line @typescript-eslint/no-unused-vars + const capEnd = vec2.create(); const lineA = vec2.create(); const lineB = vec2.create(); diff --git a/packages/map/src/map/handler/drag_handler.ts b/packages/map/src/map/handler/drag_handler.ts index 79a2ff16ebd..c553e37db0e 100644 --- a/packages/map/src/map/handler/drag_handler.ts +++ b/packages/map/src/map/handler/drag_handler.ts @@ -63,9 +63,10 @@ export type DragMoveHandlerOptions = { /** * A generic class to create handlers for drag events, from both mouse and touch events. */ -export class DragHandler - implements DragMoveHandler -{ +export class DragHandler implements DragMoveHandler< + T, + E +> { // Event handlers that may be assigned by the implementations of this class contextmenu?: Handler['contextmenu']; mousedown?: Handler['mousedown']; diff --git a/packages/map/src/map/handler/drag_move_state_manager.ts b/packages/map/src/map/handler/drag_move_state_manager.ts index c098aeb806c..47a1ec0ac0e 100644 --- a/packages/map/src/map/handler/drag_move_state_manager.ts +++ b/packages/map/src/map/handler/drag_move_state_manager.ts @@ -51,7 +51,6 @@ export class MouseMoveStateManager implements DragMoveStateManager { this._eventButton = eventButton; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars endMove(_e?: MouseEvent) { delete this._eventButton; } @@ -96,7 +95,6 @@ export class OneFingerTouchMoveStateManager implements DragMoveStateManager {} +export interface OneFingerTouchRotateHandler extends DragMoveHandler< + DragRotateResult, + TouchEvent +> {} export interface OneFingerTouchPitchHandler extends DragMoveHandler {} const assignEvents = (handler: DragHandler) => { diff --git a/packages/map/src/map/handler/two_fingers_touch.ts b/packages/map/src/map/handler/two_fingers_touch.ts index 96b1c1c0eb3..0d14877b753 100644 --- a/packages/map/src/map/handler/two_fingers_touch.ts +++ b/packages/map/src/map/handler/two_fingers_touch.ts @@ -211,7 +211,6 @@ export class TwoFingersTouchRotateHandler extends TwoFingersTouchHandler { this._minDiameter = points[0].dist(points[1]); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars _move(points: [Point, Point], pinchAround: Point | null, _e: TouchEvent): HandlerResult | void { const lastVector = this._vector!; this._vector = points[0].sub(points[1]); diff --git a/packages/maps/src/earth/map.ts b/packages/maps/src/earth/map.ts index 77c27175190..ce40d4b5302 100644 --- a/packages/maps/src/earth/map.ts +++ b/packages/maps/src/earth/map.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * MapboxService */ diff --git a/packages/maps/src/gmap/logo.css b/packages/maps/src/gmap/logo.css index dc13f1d8668..5408bf90ccd 100644 --- a/packages/maps/src/gmap/logo.css +++ b/packages/maps/src/gmap/logo.css @@ -1,4 +1,4 @@ -img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'],.logo-text -{ +img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'], +.logo-text { display: none !important; } diff --git a/packages/maps/src/lib/base-map.ts b/packages/maps/src/lib/base-map.ts index 11f9d8f1f33..febb3eba1b9 100644 --- a/packages/maps/src/lib/base-map.ts +++ b/packages/maps/src/lib/base-map.ts @@ -197,7 +197,6 @@ export default abstract class BaseMap implements IMapService { public abstract setMapStyle(name: MapStyleName): void; - // eslint-disable-next-line @typescript-eslint/no-unused-vars public meterToCoord(center: [number, number], outer: [number, number]) { return 1.0; } diff --git a/packages/maps/src/map/map.ts b/packages/maps/src/map/map.ts index 5732fca1866..b6f0baff116 100644 --- a/packages/maps/src/map/map.ts +++ b/packages/maps/src/map/map.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * MapboxService */ diff --git a/packages/maps/src/tdtmap/logo.css b/packages/maps/src/tdtmap/logo.css index dc13f1d8668..5408bf90ccd 100644 --- a/packages/maps/src/tdtmap/logo.css +++ b/packages/maps/src/tdtmap/logo.css @@ -1,4 +1,4 @@ -img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'],.logo-text -{ +img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'], +.logo-text { display: none !important; } diff --git a/packages/maps/src/tdtmap/map.ts b/packages/maps/src/tdtmap/map.ts index 45c47ef026e..cdb3ba82b11 100644 --- a/packages/maps/src/tdtmap/map.ts +++ b/packages/maps/src/tdtmap/map.ts @@ -272,7 +272,7 @@ export default class TdtMapService extends BaseMapService { offProxy(EventMap[type] || type); } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public once(type: string, handler: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } diff --git a/packages/maps/src/tmap/logo.css b/packages/maps/src/tmap/logo.css index b02ef06abab..0d83483cc49 100644 --- a/packages/maps/src/tmap/logo.css +++ b/packages/maps/src/tmap/logo.css @@ -1,5 +1,5 @@ -img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'],.logo-text -{ +img[src*='//mapapi.qq.com/web/jsapi/logo/logo_def.png'], +.logo-text { display: none !important; } diff --git a/packages/maps/src/tmap/maploader.ts b/packages/maps/src/tmap/maploader.ts index 7e8d9a8ffa2..eeca4861500 100644 --- a/packages/maps/src/tmap/maploader.ts +++ b/packages/maps/src/tmap/maploader.ts @@ -1,4 +1,3 @@ -/* eslint-disable */ if (!window) { throw Error('TMap JSAPI can only be used in Browser.'); } diff --git a/packages/renderer/src/device/utils/typedarray.ts b/packages/renderer/src/device/utils/typedarray.ts index f20b148ff09..cccea6045bf 100644 --- a/packages/renderer/src/device/utils/typedarray.ts +++ b/packages/renderer/src/device/utils/typedarray.ts @@ -22,7 +22,6 @@ export type TypedArray = | Float32Array | Float64Array; -// eslint-disable-next-line export function isTypedArray(x: any): x is TypedArray { return Object.prototype.toString.call(x) in dtypes; } diff --git a/packages/three/src/core/baseLayer.ts b/packages/three/src/core/baseLayer.ts index 1d28094bcfd..ff2f70c2451 100644 --- a/packages/three/src/core/baseLayer.ts +++ b/packages/three/src/core/baseLayer.ts @@ -120,7 +120,7 @@ export default class ThreeJSLayer * @param object * @returns */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getObjectLngLat(object: Object3D) { return [0, 0] as ILngLat; } diff --git a/packages/utils/src/geo.ts b/packages/utils/src/geo.ts index 50d8d000108..1d5dea85d53 100644 --- a/packages/utils/src/geo.ts +++ b/packages/utils/src/geo.ts @@ -225,7 +225,7 @@ export function lnglatDistance( return radiansToLength( 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)), - // eslint-disable-next-line @typescript-eslint/no-unused-vars + (units = 'meters'), ); } diff --git a/packages/utils/src/lineAtOffset/greatCircle.ts b/packages/utils/src/lineAtOffset/greatCircle.ts index ef5f466efe8..c195181c373 100644 --- a/packages/utils/src/lineAtOffset/greatCircle.ts +++ b/packages/utils/src/lineAtOffset/greatCircle.ts @@ -6,7 +6,7 @@ export function greatCircleLineAtOffset( target: Point, offset: number, thetaOffset: number | undefined, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + segmentNumber: number = 30, autoFit: boolean, ) { diff --git a/packages/utils/src/lru_cache.ts b/packages/utils/src/lru_cache.ts index 93bb095a7c3..a555d479fe2 100644 --- a/packages/utils/src/lru_cache.ts +++ b/packages/utils/src/lru_cache.ts @@ -80,7 +80,7 @@ export class LRUCache { private appendOrder(key: string) { this.order.push(key); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + private defaultDestroy(value: any, key: string) { return null; } diff --git a/site/docs/api/common/features/border.en.md b/site/docs/api/common/features/border.en.md index 35c244b378b..d309f608bb6 100644 --- a/site/docs/api/common/features/border.en.md +++ b/site/docs/api/common/features/border.en.md @@ -17,8 +17,8 @@ const layer = new LineLayer({}) .shape('arc') .color('#8C1EB2') .style({ - borderWidth: 0.35, //The default value is 0, the maximum valid value is 0.5 - borderColor: '#888', // Default is #ccc + strokeWidth: 0.4, + stroke: '#fff', }); ``` diff --git a/site/docs/api/common/features/border.zh.md b/site/docs/api/common/features/border.zh.md index 07e40860e39..da4490b0653 100644 --- a/site/docs/api/common/features/border.zh.md +++ b/site/docs/api/common/features/border.zh.md @@ -17,8 +17,8 @@ const layer = new LineLayer({}) .shape('arc') .color('#8C1EB2') .style({ - borderWidth: 0.35, // 默认文 0,最大有效值为 0.5 - borderColor: '#888', // 默认为 #ccc + strokeWidth: 0.35, // 默认文 0,最大有效值为 0.5 + stroke: '#888', // 默认为 #ccc }); ``` diff --git a/site/docs/api/line_layer/style.en.md b/site/docs/api/line_layer/style.en.md index 607a67cc446..ed661428a45 100644 --- a/site/docs/api/line_layer/style.en.md +++ b/site/docs/api/line_layer/style.en.md @@ -34,7 +34,7 @@ Universal`style`Parameters, parameters supported by all graphics. | style | type | describe | default value | | ------------- | -------------------------- | ------------------------------------------ | ------------- | | borderColor | `string` | Graphic border color | `#fff` | -| borderWidth | `number` | Graphic border radius | `0` | +| strokeWidth | `number` | Graphic border radius | `0` | | blur | `[number, number, number]` | Graphic fuzzy distribution | `[1, 1, 1]` | | raisingHeight | `number` | Lifting height | `0` | | heightfixed | `boolean` | Does the lifting height vary?`zoom`Variety | `false` | @@ -155,6 +155,43 @@ layer.style({ | arrowHeight | `number` | length of arrow | `3` | | tailWidth | `number` | Arrow tail width | `1` | +## Arrow Effect (`arrow`) + +Support for displaying direction arrows on line layers, commonly used for navigation and path indication. + +### Options + +| Property | Type | Description | +| ----------- | ------- | --------------------------- | +| enable | boolean | Whether to show arrows | +| spacing | number | Arrow spacing (pixels) | +| width | number | Arrow width (pixels) | +| length | number | Arrow length (pixels) | +| strokeWidth | number | Arrow stroke width (pixels) | +| color | string | Arrow color (CSS color) | + +### Effect Description + +- Arrows are V-shaped outlines, not solid triangles. +- Arrows are overlaid on the line, and line/arrow colors can be set independently. +- Suitable for navigation, path direction, and similar scenarios. + +### Example + +```ts +layer.style({ + color: '#0000FF', // line color + arrow: { + enable: true, + spacing: 80, + width: 30, + height: 40, + strokeWidth: 4, + color: '#FFFF00', // arrow color + }, +}); +``` + ### linear - line、arc、arc3d、greatcircle、wall、simple diff --git a/site/docs/api/line_layer/style.zh.md b/site/docs/api/line_layer/style.zh.md index 65d57d6a33f..a562f0be9e8 100644 --- a/site/docs/api/line_layer/style.zh.md +++ b/site/docs/api/line_layer/style.zh.md @@ -249,3 +249,40 @@ layer.style({ // len1 实线长度 len2 间隔长度 type IDashArray = [len1: number, len2: number] ``` + +## 箭头效果(arrow) + +支持在线图层上显示方向箭头,常用于导航、路径方向标识。 + +### 配置项 + +| 属性 | 类型 | 说明 | +| ----------- | ------- | -------------------- | +| enable | boolean | 是否显示箭头 | +| spacing | number | 箭头间距(像素) | +| width | number | 箭头宽度(像素) | +| length | number | 箭头长度(像素) | +| strokeWidth | number | 箭头线条宽度(像素) | +| color | string | 箭头颜色(CSS 色值) | + +### 效果说明 + +- 箭头为 V 形轮廓,非实心三角。 +- 箭头叠加在线本身之上,线和箭头可分别设置颜色。 +- 适用于导航、路径方向等场景。 + +### 示例代码 + +```ts +layer.style({ + color: '#0000FF', // 线颜色 + arrow: { + enable: true, + spacing: 80, + width: 30, + height: 40, + strokeWidth: 4, + color: '#FFFF00', // 箭头颜色 + }, +}); +``` diff --git a/site/docs/tutorial/line/path.en.md b/site/docs/tutorial/line/path.en.md index 19211be0197..009f8a2115d 100644 --- a/site/docs/tutorial/line/path.en.md +++ b/site/docs/tutorial/line/path.en.md @@ -54,8 +54,8 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785 opacity: 0.6, lineTexture: true, // Enable line mapping function iconStep: 10, // Set the spacing of the texture - borderWidth: 0.4, //The default value is 0, the maximum valid value is 0.5 - borderColor: '#fff', // Default is #ccc + strokeWidth: 0.4, //The default value is 0, the maximum valid value is 0.5 + stroke: '#fff', // Default is #ccc }); scene.addLayer(layer); }); diff --git a/site/docs/tutorial/line/path.zh.md b/site/docs/tutorial/line/path.zh.md index 76b0d2a1689..41d7ad6a9af 100644 --- a/site/docs/tutorial/line/path.zh.md +++ b/site/docs/tutorial/line/path.zh.md @@ -54,8 +54,8 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785 opacity: 0.6, lineTexture: true, // 开启线的贴图功能 iconStep: 10, // 设置贴图纹理的间距 - borderWidth: 0.4, // 默认文 0,最大有效值为 0.5 - borderColor: '#fff', // 默认为 #ccc + strokeWidth: 0.4, // 默认文 0,最大有效值为 0.5 + stroke: '#fff', // 默认为 #ccc }); scene.addLayer(layer); }); diff --git a/site/examples/gallery/basic/demo/meta.json b/site/examples/gallery/basic/demo/meta.json index ed73cc5e596..b951be5d1bb 100644 --- a/site/examples/gallery/basic/demo/meta.json +++ b/site/examples/gallery/basic/demo/meta.json @@ -7,7 +7,6 @@ { "filename": "province_map.ts", "title": "福建省地图", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HyCxTKbk-lsAAAAAAAAAAAAADmJ7AQ/original" }, { @@ -33,7 +32,6 @@ { "filename": "swipe.ts", "title": "卷帘对比-作物长势", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*b1WCRJjht2wAAAAAAAAAAAAADmJ7AQ/original" }, { diff --git a/site/examples/gallery/story/demo/meta.json b/site/examples/gallery/story/demo/meta.json index 9fd6fc45c73..e46a9f68f18 100644 --- a/site/examples/gallery/story/demo/meta.json +++ b/site/examples/gallery/story/demo/meta.json @@ -7,19 +7,16 @@ { "filename": "gaza.js", "title": "加沙", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VN1hSZkDpg0AAAAAAAAAAAAADmJ7AQ/original" }, { "filename": "yidaiyilu.js", "title": "一带一路", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9UiMQ4FVlS8AAAAAAAAAAAAADmJ7AQ/original" }, { "filename": "yidaiyilu2.js", "title": "一带一路GDP", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wXUpR4OJ4SMAAAAAAAAAAAAADmJ7AQ/original" } ] diff --git a/site/examples/line/path/demo/line_arrow.js b/site/examples/line/path/demo/line_arrow.js new file mode 100644 index 00000000000..5303d389e92 --- /dev/null +++ b/site/examples/line/path/demo/line_arrow.js @@ -0,0 +1,39 @@ +/** + * Arrow Path Demo + * 展示带箭头的路径线效果,适用于导航、路径方向等场景。 + */ +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [103.83735, 1.3602538], + zoom: 9.4678190476727, + pitch: 20, + style: 'dark', + }), +}); + +scene.on('loaded', async () => { + const data = await ( + await fetch('https://gw.alipayobjects.com/os/rmsportal/dzpMOiLYBKxpdmsgBLoE.json') + ).json(); + const layer = new LineLayer({}) + .source(data) + .shape('line') + .size(4) + .color('#16f') + .style({ + arrow: { + enable: true, + spacing: 10, + width: 8, + height: 4, + strokeWidth: 4, + color: '#FFF', + }, + }); + + scene.addLayer(layer); +}); diff --git a/site/examples/line/path/demo/meta.json b/site/examples/line/path/demo/meta.json index e79b5259401..ddf9293029b 100644 --- a/site/examples/line/path/demo/meta.json +++ b/site/examples/line/path/demo/meta.json @@ -33,6 +33,11 @@ "filename": "road_dark_dash.js", "title": "路径虚线", "screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*vZFUTaBCGoEAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "line_arrow.js", + "title": "路径箭头", + "screenshot": "https://mdn.alipayobjects.com/huamei_dxq8v0/afts/img/F5DrRp3Mn5gAAAAATJAAAAgADu43AQFr/original" } ] } diff --git a/site/examples/line/path/demo/road_dark.js b/site/examples/line/path/demo/road_dark.js index 422b518840c..35fb4f8a0e7 100644 --- a/site/examples/line/path/demo/road_dark.js +++ b/site/examples/line/path/demo/road_dark.js @@ -20,8 +20,8 @@ scene.on('loaded', () => { .shape('line') .color('标准名称', ['#5B8FF9', '#5CCEA1', '#F6BD16']) .style({ - borderWidth: 0.4, - borderColor: '#fff', + strokeWidth: 1, + stroke: '#fff', }); scene.addLayer(layer); }); diff --git a/site/examples/map/map/demo/meta.json b/site/examples/map/map/demo/meta.json index 734b08972ef..39b022e0a3b 100644 --- a/site/examples/map/map/demo/meta.json +++ b/site/examples/map/map/demo/meta.json @@ -47,7 +47,6 @@ { "filename": "tianditu.js", "title": "天地图", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*10TuSJ9OF7EAAAAAAAAAAAAADmJ7AQ/original" } ] diff --git a/site/examples/polygon/extrusion/demo/meta.json b/site/examples/polygon/extrusion/demo/meta.json index 6bb758983ee..ff31672a480 100644 --- a/site/examples/polygon/extrusion/demo/meta.json +++ b/site/examples/polygon/extrusion/demo/meta.json @@ -7,7 +7,6 @@ { "filename": "polygon.js", "title": "室内地图", - "new": true, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*fEdKQbiYq0kAAAAAAAAAAAAADmJ7AQ/original" } ]