[英]How to add Multiple animated arrow icon on single line string in open layers
[英]How to add animated arrow as per the value I have entered in text box in open layers
我試圖根據我們在文本框中輸入的值在字符串上一個一個地添加動畫箭頭,但這是不可能的。 可以告訴我如何添加這個。
我想當我們在文本框中輸入 4 然后單擊添加箭頭按鈕然后在行字符串中的 2 秒間隙中一個接一個地添加 4 個動畫箭頭圖標。
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Map from 'ol/Map';
import Point from 'ol/geom/Point';
import Polyline from 'ol/format/Polyline';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import OSM from 'ol/source/OSM';
import {Icon, Stroke, Style} from 'ol/style';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {getVectorContext} from 'ol/render';
const center = [-5639523.95, -3501274.52];
const map = new Map({
target: document.getElementById('map'),
view: new View({
center: center,
zoom: 10,
minZoom: 2,
maxZoom: 19,
}),
layers: [
new TileLayer({
source: new OSM(),
}),
],
});
// The polyline string is read from a JSON similiar to those returned
// by directions APIs such as Openrouteservice and Mapbox.
fetch('data/polyline/route.json').then(function (response) {
response.json().then(function (result) {
const polyline = result.routes[0].geometry;
const route = new Polyline({
factor: 1e6,
}).readGeometry(polyline, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857',
});
const routeFeature = new Feature({
type: 'route',
geometry: route,
});
const startMarker = new Feature({
type: 'icon',
geometry: new Point(route.getFirstCoordinate()),
});
const endMarker = new Feature({
type: 'icon',
geometry: new Point(route.getLastCoordinate()),
});
const position = startMarker.getGeometry().clone();
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position,
});
const styles = {
route: new Style({
stroke: new Stroke({
width: 6,
color: [237, 212, 0, 0.8],
}),
}),
icon: new Style({
image: new Icon({
anchor: [0.5, 1],
src: 'data/icon.png',
}),
}),
geoMarker: new Style({
image: new Icon({
src:
'https://cdn1.iconfinder.com/data/icons/basic-ui-elements-color-round/3/19-32.png',
rotation: getAngleAt(route, 0) + Math.PI / 2,
}),
}),
};
const vectorLayer = new VectorLayer({
source: new VectorSource({
features: [routeFeature, geoMarker, startMarker, endMarker],
}),
style: function (feature) {
return styles[feature.get('type')];
},
});
map.addLayer(vectorLayer);
const speedInput = document.getElementById('speed');
const startButton = document.getElementById('start-animation');
let animating = false;
function getAngleAt(lineString, distance) {
const length = lineString.getLength();
const coordinates = lineString.getCoordinates();
for (let i = 1, len = coordinates.length; i <= len; ++i) {
if (
new LineString(coordinates.slice(0, i + 1)).getLength() >=
length * distance
) {
return -Math.atan2(
coordinates[i][1] - coordinates[i - 1][1],
coordinates[i][0] - coordinates[i - 1][0]
);
}
}
}
const lastTimes = [];
function moveFeature(event) {
const speed = Number(speedInput.value);
const time = event.frameState.time;
for (let i = 0, ii = lastTimes.length; i < ii; ++i) {
let {lastTime, distance} = lastTimes[i];
const elapsedTime = time - lastTime;
distance = (distance + (speed * elapsedTime) / 1e6) % 2;
lastTime = time;
lastTimes[i] = {lastTime, distance};
const lineDistance = distance > 1 ? 2 - distance : distance;
const direction = distance > 1 ? -Math.PI / 2 : Math.PI / 2;
const currentCoordinate = route.getCoordinateAt(lineDistance);
const angle = getAngleAt(route, lineDistance) + direction;
styles.geoMarker.getImage().setRotation(angle);
position.setCoordinates(currentCoordinate);
const vectorContext = getVectorContext(event);
vectorContext.setStyle(styles.geoMarker);
vectorContext.drawGeometry(position);
}
// tell OpenLayers to continue the postrender animation
map.render();
}
function startAnimation() {
lastTimes.push({lastTime: Date.now(), distance: 0});
if (!animating) {
animating = true;
//startButton.textContent = 'Stop Animation';
vectorLayer.on('postrender', moveFeature);
// hide geoMarker and trigger map render through change event
geoMarker.setGeometry(null);
}
}
startButton.addEventListener('click', startAnimation);
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Marker Animation</title>
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<label for="speed">
speed:
<input id="speed" type="range" min="10" max="999" step="10" value="60">
</label>
<button id="start-animation">Start Animation</button>
<input type="text" id="textValue">
<button id="btnClick">Add icon</button>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep@1.0.6/dist/elm-pep.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>
我正在嘗試使用此代碼根據文本框值添加動畫箭頭,但沒有獲得有關如何添加它的任何解決方案。
請查看我的圖像以了解我想要的內容。
您需要以 500 毫秒的間隔啟動每個 animation,直到啟動了所需數量的箭頭:
function startAnimations() {
const arrows = Number(arrowsInput.value);
if (arrows > 0) {
let count = 0;
const id = setInterval(function () {
startAnimation();
++count;
if (count === arrows) {
clearInterval(id);
}
}, 500);
}
}
startButton.addEventListener('click', startAnimations);
https://codesandbox.io/s/feature-move-animation-forked-2ckr74
要沿路徑移動元素,只需使用方法getPointAtLength
所以想象一下我們有一些像:
div class="wrapper">
<svg viewBox="-5 -5 173 61" width="173" heigth="61">
<path
#path
d="M153,20.89c0-45.88-74.95,0-74.95,0S.5,66.76.5,20.89s77.54,0,77.54,0S153,66.76,153,20.89Z"
fill="none"
stroke="#000"
vector-effect="non-scaling-stroke"
class="infinity"
/>
</svg>
<div #circle class="element"></div>
</div>
<button (click)="click()">start</button>
.css
.wrapper{
position:relative
}
.element{
position:absolute;
width:10px;
height:10px;
background-color:blueviolet;
border-radius: 5px;
top:0;
left:0;
}
代碼:
@ViewChild('path',{static:true}) path:ElementRef
@ViewChild('circle',{static:true}) circle:ElementRef
subscription:any
distance:number
fps:number=32
duration:number=2*this.fps
time:number;
ngOnInit()
{
this.distance=this.path.nativeElement.getTotalLength()
const pos=this.path.nativeElement.getPointAtLength(0)
this.circle.nativeElement.style.left=pos.x+'px'
this.circle.nativeElement.style.top=pos.y+'px'
}
ngOnDestroy(){
this.subscription && this.subscription.unsubscribe()
}
click(){
this.subscription=timer(0,1000/this.fps).pipe(
take(this.duration+1)
).subscribe(x=>{
const pos=this.path.nativeElement.getPointAtLength(x*this.distance/this.duration)
this.circle.nativeElement.style.left=pos.x+'px'
this.circle.nativeElement.style.top=pos.y+'px'
})
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.