fix: 修复点图层stroke模糊问题

This commit is contained in:
thinkinggis 2020-04-02 19:53:36 +08:00
parent f8ae7322e6
commit 092814d3a7
19 changed files with 210 additions and 47 deletions

View File

@ -1,6 +1,7 @@
import EventEmitter from 'eventemitter3';
import Hammer from 'hammerjs';
import { inject, injectable } from 'inversify';
// @ts-ignore
import { TYPES } from '../../types';
import { ILogService } from '../log/ILogService';
import { ILngLat, IMapService } from '../map/IMapService';
@ -58,10 +59,20 @@ export default class InteractionService extends EventEmitter
private addEventListenerOnMap() {
const $containter = this.mapService.getMapContainer();
Hammer.defaults.domEvents = true;
if ($containter) {
const hammertime = new Hammer.Manager($containter);
hammertime.add(new Hammer.Tap({ event: 'dblclick', taps: 2 }));
hammertime.add(new Hammer.Tap({ event: 'click' }));
hammertime.add(
new Hammer.Tap({
event: 'dblclick',
taps: 2,
}),
);
hammertime.add(
new Hammer.Tap({
event: 'click',
}),
);
hammertime.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
hammertime.add(new Hammer.Press({}));
// hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
@ -86,10 +97,10 @@ export default class InteractionService extends EventEmitter
const $containter = this.mapService.getMapContainer();
if ($containter) {
$containter.removeEventListener('mousemove', this.onHover);
this.hammertime.off('dblclick click', this.onHammer);
// this.hammertime.off('dblclick click', this.onHammer);
this.hammertime.off('panstart panmove panend pancancel', this.onDrag);
// $containter.removeEventListener('touchstart', this.onTouch);
// $containter.removeEventListener('click', this.onHover);
$containter.removeEventListener('touchstart', this.onTouch);
$containter.removeEventListener('click', this.onHover);
$containter.removeEventListener('mousedown', this.onHover);
$containter.removeEventListener('mouseup', this.onHover);
// $containter.removeEventListener('dblclick', this.onHover);
@ -102,9 +113,19 @@ export default class InteractionService extends EventEmitter
this.emit(InteractionEvent.Drag, interactionTarget);
};
private onHammer = (target: HammerInput) => {
target.srcEvent.stopPropagation();
const interactionTarget = this.interactionEvent(target);
this.emit(InteractionEvent.Hover, interactionTarget);
};
private onTouch = (target: TouchEvent) => {
const touch = target.touches[0];
// @ts-ignore
this.onHover({
x: touch.pageX,
y: touch.pageY,
type: 'touch',
});
};
private interactionEvent(target: HammerInput) {
const { type, pointerType } = target;
@ -147,7 +168,7 @@ export default class InteractionService extends EventEmitter
this.isDoubleTap(x, y, lngLat);
return;
}
if (type !== 'click' || type !== 'click') {
if (type !== 'click' && type !== 'dblclick') {
this.emit(InteractionEvent.Hover, {
x,
y,
@ -161,7 +182,7 @@ export default class InteractionService extends EventEmitter
const nowTime = new Date().getTime();
let type = 'click';
if (
nowTime - this.lastClickTime < 500 &&
nowTime - this.lastClickTime < 400 &&
Math.abs(this.lastClickXY[0] - x) < 10 &&
Math.abs(this.lastClickXY[1] - y) < 10
) {
@ -179,7 +200,7 @@ export default class InteractionService extends EventEmitter
this.clickTimer = setTimeout(() => {
type = 'click';
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
}, 500);
}, 400);
}
}
}

View File

@ -3,7 +3,7 @@
background: #fff;
box-shadow: 0 0 0 1px rgba(0,0,0,.1);
display: flex;
button {
a {
background-repeat: no-repeat;
background-position: center;
background-size: 20px 20px;
@ -17,16 +17,11 @@
box-sizing: border-box;
cursor: pointer;
}
button+button {
border-top: 1px solid #ddd;
a:not(:disabled):hover {
background-color: rgba(0, 0, 0, 0.05);
}
button:not(:disabled):hover {
background-color: rgba(255, 255, 255, 0.9);
}
button:focus:first-child {
border-radius: 4px 4px 0 0;
}
button:focus {
a:focus {
box-shadow: 0 0 2px 2px #0096ff;
}
.draw-point {
@ -44,5 +39,32 @@
.draw-circle {
background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/fa234d68-85aa-4628-b1b6-aad47ab093b4.svg');
}
.draw-delete {
background-image: url('https://gw.alipayobjects.com/zos/bmw-prod/0c9ba44b-aba3-4007-ba4e-ab815279886b.svg');
}
}
.horizontal {
flex-direction: row;
a:focus:first-child {
border-radius: 4px 0px 0px 4px;
}
a:focus:last-child {
border-radius: 0px 4px 4px 4px;
}
a+a {
border-left: 1px solid #eee;
}
}
.vertical {
flex-direction: column;
a:focus:first-child {
border-radius: 4px 4px 0 0;
}
a:focus:last-child {
border-radius: 0px 0px 4px 4px;
}
a+a {
border-top: 1px solid #eee;
}
}

View File

@ -1,10 +1,12 @@
import { Control, IControlOption, PositionType, Scene } from '@antv/l7';
import { DOM } from '@antv/l7-utils';
import Hammer from 'hammerjs';
import './css/draw.less';
import {
DrawCircle,
DrawDelete,
DrawFeature,
DrawLine,
DrawMode,
DrawPoint,
DrawPolygon,
DrawRect,
@ -20,8 +22,10 @@ export interface IDrawControlOption extends IControlOption {
}
export class DrawControl extends Control {
private draw: {
[key: string]: DrawMode;
[key: string]: DrawFeature;
} = {};
private drawDelete: DrawDelete;
private currentDraw: DrawFeature;
private scene: Scene;
constructor(scene: Scene, options: Partial<IDrawControlOption>) {
super(options);
@ -39,11 +43,10 @@ export class DrawControl extends Control {
}
public onAdd(): HTMLElement {
const controlClass = 'l7-control-draw';
const { layout } = this.controlOption;
const controlClass = 'l7-control-draw' + ' ' + layout;
const { controls } = this.controlOption as IDrawControlOption;
const container = DOM.create('div', controlClass) as HTMLElement;
container.style.flexDirection =
this.controlOption.layout === 'vertical' ? 'column' : 'row';
if (controls.point) {
this.draw.point = new DrawPoint(this.scene);
this.createButton(
@ -89,6 +92,16 @@ export class DrawControl extends Control {
this.onButtonClick.bind(null, 'circle'),
);
}
if (controls.delete) {
this.drawDelete = new DrawDelete(this.scene);
this.createButton(
'删除',
'draw-delete',
container,
this.onDeleteMode.bind(null, 'delete'),
);
}
return container;
}
@ -98,19 +111,29 @@ export class DrawControl extends Control {
container: HTMLElement,
fn: (...arg: any[]) => any,
) {
const link = DOM.create('button', className, container) as HTMLLinkElement;
const link = DOM.create('a', className, container) as HTMLLinkElement;
link.href = 'javascript:void(0)';
link.title = tile;
link.addEventListener('click', fn);
link.addEventListener('click', fn, false);
return link;
}
private onButtonClick = (type: string) => {
private onButtonClick = (type: string, e: MouseEvent) => {
for (const draw in this.draw) {
if (draw === type) {
this.draw[draw].enable();
this.currentDraw = this.draw[draw];
} else {
this.draw[draw].disable();
}
}
};
private onDeleteMode = (type: string, e: MouseEvent) => {
// e.stopPropagation();
if (!this.currentDraw) {
return;
}
return false;
};
}

View File

@ -118,7 +118,9 @@ export default class DrawCircle extends DrawFeature {
}
protected hideOtherLayer() {
this.centerLayer.hide();
if (this.currentFeature) {
this.centerLayer.hide();
}
}
private initCenterLayer() {

View File

@ -0,0 +1,38 @@
import { IInteractionTarget, ILngLat, Scene } from '@antv/l7';
import { Feature } from '@turf/helpers';
import { DrawEvent } from '../util/constant';
import DrawFeature, { IDrawOption } from './draw_mode';
export type unitsType = 'degrees' | 'radians' | 'miles' | 'kilometers';
export interface IDrawCircleOption extends IDrawOption {
units: unitsType;
steps: number;
}
export default class DrawDelete extends DrawFeature {
private endPoint: ILngLat;
// 绘制完成之后显示
constructor(scene: Scene, options: Partial<IDrawCircleOption> = {}) {
super(scene, options);
}
public enable() {
this.emit(DrawEvent.DELETE, '');
}
public disable() {
return null;
}
protected onDragStart(e: any): void {
throw new Error('Method not implemented.');
}
protected onDragging = (e: IInteractionTarget) => {
return;
};
protected onDragEnd = () => {
throw new Error('Method not implemented.');
};
protected onClick = () => {
return null;
};
}

View File

@ -1,6 +1,4 @@
import { IInteractionTarget, ILayer, ILngLat, Popup, Scene } from '@antv/l7';
import turfCircle from '@turf/circle';
import turfDistance from '@turf/distance';
import {
Feature,
FeatureCollection,
@ -11,6 +9,7 @@ import DrawRender from '../render/draw';
import RenderLayer from '../render/draw_result';
import DrawVertexLayer from '../render/draw_vertex';
import { DrawEvent, DrawModes, unitsType } from '../util/constant';
import DrawDelete from './draw_delete';
import DrawEdit from './draw_edit';
import DrawMode, { IDrawOption } from './draw_mode';
import DrawSelected from './draw_selected';
@ -26,6 +25,8 @@ export default abstract class DrawFeature extends DrawMode {
// 绘制完成之后显示
public selectMode: DrawSelected;
public editMode: DrawEdit;
public deleteMode: DrawDelete;
protected renderLayer: RenderLayer;
protected drawRender: DrawRender;
protected drawVertexLayer: DrawVertexLayer;
@ -43,12 +44,16 @@ export default abstract class DrawFeature extends DrawMode {
// this.editLayer = new EditLayer(this);
this.selectMode = new DrawSelected(this.scene, {});
this.editMode = new DrawEdit(this.scene, {});
this.deleteMode = new DrawDelete(this.scene, {});
this.selectMode.on(DrawEvent.UPDATE, this.onDrawUpdate);
this.selectMode.on(DrawEvent.Move, this.onDrawMove);
this.editMode.on(DrawEvent.MODE_CHANGE, this.onModeChange);
this.editMode.on(DrawEvent.UPDATE, this.onDrawUpdate);
this.editMode.on(DrawEvent.Edit, this.onDrawEdit);
this.selectMode.on(DrawEvent.MODE_CHANGE, this.onModeChange);
this.deleteMode.on(DrawEvent.DELETE, this.onDrawDelete);
this.on(DrawEvent.CREATE, this.onDrawCreate);
this.on(DrawEvent.MODE_CHANGE, this.onModeChange);
}
@ -61,6 +66,16 @@ export default abstract class DrawFeature extends DrawMode {
this.source.setFeatureActive(feature);
}
public deleteCurrentFeature() {
this.deleteMode.enable();
}
public disableLayer() {
// this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
this.drawRender.disableDrag();
}
public enableLayer() {
this.drawRender.enableDrag();
}
public addVertex(feature: Feature): void {
throw new Error('子类未实现该方法');
@ -113,6 +128,7 @@ export default abstract class DrawFeature extends DrawMode {
this.drawVertexLayer.show();
this.drawVertexLayer.enableEdit();
this.showOtherLayer();
this.drawStatus = 'DrawEdit';
break;
case DrawModes.SIMPLE_SELECT:
this.selectMode.setSelectedFeature(this.currentFeature as Feature);
@ -128,6 +144,7 @@ export default abstract class DrawFeature extends DrawMode {
this.drawVertexLayer.show();
this.drawRender.show();
this.showOtherLayer();
this.drawStatus = 'DrawSelected';
break;
case DrawModes.STATIC:
this.source.updateFeature(this.currentFeature as Feature);
@ -137,6 +154,7 @@ export default abstract class DrawFeature extends DrawMode {
this.hideOtherLayer();
this.renderLayer.update(this.source.data);
this.renderLayer.enableDrag();
this.drawStatus = 'DrawFinish';
break;
}
};
@ -156,4 +174,11 @@ export default abstract class DrawFeature extends DrawMode {
private onDrawEdit = (endpoint: ILngLat) => {
this.editFeature(endpoint);
};
private onDrawDelete = () => {
if (this.drawStatus === 'DrawSelected') {
this.source.removeFeature(this.currentFeature as Feature);
this.emit(DrawEvent.MODE_CHANGE, DrawModes.STATIC);
}
};
}

View File

@ -76,6 +76,9 @@ export default abstract class DrawMode extends EventEmitter {
public setCurrentVertex(feature: Feature) {
this.currentVertex = feature;
}
public deleteCurrentFeature() {
throw new Error('子类未实现该方法');
}
public getCurrentVertex(feature: Feature) {
return this.currentVertex;

View File

@ -51,11 +51,16 @@ export default class DrawPoint extends DrawFeature {
this.drawVertexLayer.updateData(featureCollection(newFeature));
this.currentFeature = newFeature[0];
this.pointFeatures = newFeature;
this.currentFeature.properties = {
...this.currentFeature.properties,
pointFeatures: newFeature,
};
return this.currentFeature;
}
protected createFeature(p: ILngLat): Feature {
const feature = point([p.lng, p.lat], {
id: this.getUniqId(),
pointFeatures: [point([p.lng, p.lat])],
});
this.setCurrentFeature(feature as Feature);
return feature;

View File

@ -50,7 +50,6 @@ export default class DrawPolygon extends DrawFeature {
this.drawVertexLayer.update(featureCollection(properties.pointFeatures));
// @ts-ignore
// feature.properties.pointFeatures = pointfeatures;
// console.log(feature);
this.emit(DrawEvent.CREATE, this.currentFeature);
this.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
this.points = [];

View File

@ -1,7 +1,18 @@
import DrawCircle from './draw_circle';
import DrawDelete from './draw_delete';
import DrawFeature from './draw_feature';
import DrawLine from './draw_line';
import DrawMode from './draw_mode';
import DrawPoint from './draw_point';
import DrawPolygon from './draw_polygon';
import DrawRect from './draw_rect';
export { DrawCircle, DrawRect, DrawPolygon, DrawPoint, DrawLine, DrawMode };
export {
DrawCircle,
DrawFeature,
DrawRect,
DrawPolygon,
DrawPoint,
DrawLine,
DrawMode,
DrawDelete,
};

View File

@ -30,6 +30,16 @@ export default class DrawResultLayer extends BaseRender {
layer.off('click', this.onClick);
this.isEnableDrag = false;
}
public enableDelete() {
this.disableDrag();
const layer = this.drawLayers[0];
layer.on('click', this.onDeleteClick);
}
public disableDelete() {
const layer = this.drawLayers[0];
layer.off('click', this.onDeleteClick);
}
public addFilter() {
this.drawLayers.forEach((layer) =>
layer.filter('active', (active) => {
@ -41,10 +51,14 @@ export default class DrawResultLayer extends BaseRender {
this.draw.source.setFeatureUnActive(
this.draw.getCurrentFeature() as Feature,
);
// console.log(e.feature);
this.draw.setCurrentFeature(e.feature);
this.draw.source.setFeatureActive(e.feature as Feature);
this.updateData(this.draw.source.data);
this.draw.emit(DrawEvent.MODE_CHANGE, DrawModes.SIMPLE_SELECT);
};
private onDeleteClick = (e: any) => {
this.draw.source.removeFeature(e.feature);
this.updateData(this.draw.source.data);
};
}

View File

@ -28,6 +28,7 @@ export default class DrawSource {
fe.properties.active = true;
}
}
public setFeatureUnActive(feature: Feature) {
const fe = this.getFeature(feature?.properties?.id);
if (fe && fe.properties) {

View File

@ -55,12 +55,6 @@ void main() {
}
float opacity_t = smoothstep(0.0, antialiased_blur, outer_df);
if(u_stroke_width <0.01 ) {
gl_FragColor = v_color * opacity_t;
gl_FragColor.a = gl_FragColor.a * u_opacity;
gl_FragColor = filterColor(gl_FragColor);
return;
}
float color_t = u_stroke_width < 0.01 ? 0.0 : smoothstep(
antialiased_blur,
0.0,
@ -73,8 +67,8 @@ void main() {
// gl_FragColor = v_color * color_t;
// gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor = opacity_t * mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), strokeColor * u_stroke_opacity, color_t);
gl_FragColor.a = gl_FragColor.a * opacity_t;
if(u_aimate.x == Animate) {
float d = length(v_data.xy);
float intensity = clamp(cos(d * PI), 0.0, 1.0) * clamp(cos(2.0 * PI * (d * 2.0 * u_aimate.z - u_aimate.y * u_time)), 0.0, 1.0);

View File

@ -33,7 +33,7 @@ void main() {
// TODO: billboard
// anti-alias
float antialiasblur = 1.0 / (newSize + u_stroke_width);
float antialiasblur = 1.0 / u_DevicePixelRatio / (newSize + u_stroke_width);
// construct point coords
v_data = vec4(extrude, antialiasblur,shape_type);

View File

@ -25,5 +25,6 @@ float r = 1.0 - smoothstep(radius-(radius*0.01),
}else {
gl_FragColor= step(0.01, textureColor.z) * v_color;
}
gl_FragColor.a =gl_FragColor.a * u_opacity;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -29,6 +29,7 @@ void main() {
highp float gamma_scaled = gamma * v_gamma_scale;
highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), vec4(u_stroke.rgb, u_stroke.a * u_opacity), smoothstep(0., 0.5, 1. - dist)) * alpha;
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * u_opacity), vec4(u_stroke.rgb, u_stroke.a * u_opacity), smoothstep(0., 0.5, 1. - dist));
gl_FragColor.a= gl_FragColor.a * alpha;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -25,15 +25,17 @@ export default class Circle extends React.Component {
scene.on('loaded', () => {
const drawControl = new DrawControl(scene, {
position: 'topright',
layout: 'vertical', // horizontal vertical
layout: 'horizontal', // horizontal vertical
controls: {
point: true,
polygon: true,
line: true,
circle: true,
rect: true,
delete: true,
},
});
scene.on('click', () => {});
scene.addControl(drawControl);
});
}

View File

@ -18,7 +18,7 @@ export default class Point3D extends React.Component {
style: 'light',
center: [-121.24357, 37.58264],
pitch: 0,
zoom: 6.45,
zoom: 10.45,
}),
});
scene.on('loaded', () => {
@ -53,6 +53,7 @@ export default class Point3D extends React.Component {
.style({
opacity: 1,
strokeWidth: 0,
stroke: '#fff',
});
scene.addLayer(pointLayer);

View File

@ -23,7 +23,7 @@ export default class TextLayerDemo extends React.Component {
const scene = new Scene({
id: 'map',
map: new Mapbox({
map: new GaodeMap({
center: [120.19382669582967, 30.258134],
pitch: 0,
style: 'dark',
@ -41,7 +41,7 @@ export default class TextLayerDemo extends React.Component {
})
.shape('s', 'text')
// .shape('circle')
.size(8)
.size(18)
.filter('t', (t) => {
return t < 5;
})
@ -54,7 +54,7 @@ export default class TextLayerDemo extends React.Component {
// spacing: 2, // 字符间距
// padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
stroke: '#fff', // 描边颜色
strokeWidth: 0, // 描边宽度
strokeWidth: 1, // 描边宽度
// strokeOpacity: 1.0,
});
scene.addLayer(pointLayer);