LeafletJS marcador animado con video

8

He usado los leaflet.animatedmarkerplanos abiertos de GitHub para crear un marcador que se mueve a lo largo de una línea. También he agregado un video que aparecerá sobre la línea. Esto juega bien con el marcador en movimiento.

Lo que quiero poder hacer es tener un botón que pueda iniciar y pausar el video y el marcador al mismo tiempo. También me gustaría el beneficio adicional de poder avanzar y retroceder en el video y el marcador en la línea. Me pregunto si esto es posible y cómo podría hacerlo.

usuario3579273
fuente
3
publicar su código (o un enlace a su código, sitio web o jsfiddle) podría ayudar a obtener más atención a su pregunta
sfletche
Esto es similar mapbox.com/blog/gopro-video-maps
gomapping

Respuestas:

6

Si bien ha escrito el código básico para el L.animatedMarker, lo detallaré para obtener más educación. He usado algunas referencias externas, como el tutorial Mapbox GoPro y un JSFiddle en la publicación de StackExchange que describe los eventos de Vimeo.

Puede ver mi resultado en el siguiente JSFiddle: http://jsfiddle.net/GFarkas/4mo8e9da/ . Desafortunadamente, no puede probar el "beneficio adicional de poder avanzar y retroceder en el video y el marcador en la línea". Sin embargo, puede probarlo en un sitio alojado local.

En la primera línea de código 9 configura un mapa Mapbox básico con Leaflet. Tiene un centro y un nivel de zoom predefinido. A partir de entonces, puede pasar a la línea 638, ese código largo es solo un código GeoJSON copiado.

La siguiente parte del código representa la línea GeoJSON en el mapa como una característica de línea simple.

var line = L.geoJson(ride, {
    style: {
        weight: 7,
        opacity: 1,
        color: '#0d8709',
        opacity: 0.7
    }
});

En la siguiente parte, tuve que extraer las coordenadas de la matriz GeoJSON y cambiar los valores lan / lot, porque el formato GeoJSON usa el orden de coordenadas lon / lat. He usado un bucle para esta tarea.

var raw = [];

for (var i = 0; i < ride.features[0].geometry.coordinates.length; i++) {
    var tmp = [];
    tmp[0] = ride.features[0].geometry.coordinates[i][1];
    tmp[1] = ride.features[0].geometry.coordinates[i][0];
    raw.push(tmp);
}

Ahora que tenía una matriz de coordenadas ordenada correctamente, podría haber hecho una entidad de polilínea, que es la única entrada válida L.animatedMarkerhasta donde yo sé.

var coords = L.polyline(raw),
    animatedMarker = L.animatedMarker(coords.getLatLngs(), {
        distance: 100,
        interval: 2500,
        autoStart: false
});

Las opciones distancey intervaldefinen la velocidad del marcador en la línea. Tienes que ajustarlo, para que tu video termine al mismo tiempo que tu marcador. También tuve que configurar la autoStartopción false, para luego poder comenzar el marcador con el video.

De ahora en adelante, aquí viene la parte "mágica". Si desea tener control sobre su video y su marcador simultáneamente, debe usar la API de su sitio favorito además de Leaflet. En este ejemplo he usado el framework Froogaloop de Vimeo. Si desea incrustar un video de YouTube, debe buscar cómo puede usar su API para esta tarea. En el siguiente paso, agregué la L.popupcapa y la uní al marcador.

var popup = L.popup({
    keepInView: false,
    autoPan: false,
    closeButton: false,
    closeOnClick: false,
    maxWidth: 1000
}).setContent('<iframe id="player1" src="https://player.vimeo.com/video/69426498?title=0&amp;byline=0&amp;portrait=0&amp;autoplay=0&amp;api=1&amp;player_id=player1" width="200" height="150" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>');

animatedMarker.bindPopup(popup).openPopup();

La opción más importante en este objeto es el contenido. Debe agregar una identificación a la iframeetiqueta e incluirla en el enlace del video, también como una solicitud con &player_id=player1. También debe incluir una solicitud para usar la API de Vimeo con &api=1.

Usé un código de muestra para escribir los oyentes del evento para los videos. El código de muestra usaba JQuery, así que yo y yo solo detallaremos la parte personalizada del código.

player.addEvent('ready', function() {
    player.addEvent('pause', onPause);
    player.addEvent('finish', onFinish);
    player.addEvent('play', onPlay);
    player.addEvent('seek', onSeek);
});

Necesitaremos cuatro eventos del video. Tenemos que saber si está en pausa ( pause), si está terminado ( finish), si se está reproduciendo ( play) o si saltamos al video ( seek). Precaución: no use el playProgressevento para vincularlo animatedMarker.start(), hará que el marcador se acelere sin control. Ahora para crear las funciones adecuadas para los eventos.

function onPause(id) {
    animatedMarker.stop();
}

function onFinish(id) {
    animatedMarker.stop();
}

function onPlay(id) {
    animatedMarker.start();
}

function onSeek(data, id) {
    animatedMarker._i = Math.round(data.percent*raw.length);
}

Los primeros tres eventos devolverán una función para iniciar o detener el marcador en la línea si el video se ha iniciado o detenido. El cuarto evento es un poco diferente. Para mover el marcador en el mapa con el video, tenemos que usar una fórmula para configurar el nuevo lugar del marcador en el mapa. El lugar actual del marcador (vértice en la polilínea) se almacena en el marker._iatributo si L.animatedMarkerse llama a la variable de su marker. Afortunadamente elseekEl evento devuelve un objeto con la duración, posición y porcentaje reproducido del video (en una escala entre 0 y 1). Si devolvemos el vértice más cercano al número de vértices multiplicado por el porcentaje deseado del video, y lo redondeamos al número entero más cercano, obtenemos la posición del marcador en la línea en el momento deseado del video con una buena aproximación. Puede optimizar la precisión de este método haciendo que la duración del movimiento del marcador sea tan larga como el video y trabajando con muchos puntos (por supuesto, solo funciona bien si los vértices están igualmente distribuidos en la línea).

Espero que esta respuesta ayude y lo siento por mi mal inglés.

ACTUALIZAR:

Si desea que su marcador siga sus instrucciones cuando el video está en pausa, no podrá usarlo L.animatedMarker.update(). Tienes que usar L.animatedMarker.start()y lo L.animatedMarker.stop()que hará que el marcador salte sobre un vértice. Desafortunadamente, esto reducirá la precisión de la animación, pero este es el precio que tiene que pagar por un mapa interactivo (hasta que el (los) autor (es) arreglen la L.animatedMarker.update()función).

Gabor Farkas
fuente