Trong khi bạn đã viết mã cơ bản cho L.animatedMarker
, tôi sẽ trình bày chi tiết về nó cho giáo dục nâng cao. Tôi đã sử dụng một số tài liệu tham khảo bên ngoài, như hướng dẫn về Mapbox GoPro và một JSFiddle trong bài đăng StackExchange mô tả các sự kiện Vimeo.
Bạn có thể thấy kết quả của tôi trên JSFiddle sau: http://jsfiddle.net/GFarkas/4mo8e9da/ . Thật không may, bạn không thể kiểm tra "lợi ích bổ sung của việc có thể di chuyển tiến và lùi trong video và điểm đánh dấu trên dòng". Tuy nhiên, bạn có thể kiểm tra nó trên một trang web lưu trữ cục bộ.
Trên 9 dòng mã đầu tiên, bạn thiết lập bản đồ Mapbox cơ bản với Tờ rơi. Nó có một trung tâm và mức thu phóng được xác định trước. Từ đó, bạn có thể bỏ qua dòng 638, mã dài đó chỉ là mã GeoJSON được sao chép.
Phần tiếp theo của mã sẽ hiển thị dòng GeoJSON trên bản đồ dưới dạng một tính năng dòng đơn giản.
var line = L.geoJson(ride, {
style: {
weight: 7,
opacity: 1,
color: '#0d8709',
opacity: 0.7
}
});
Trong phần tiếp theo, tôi phải trích xuất tọa độ từ mảng GeoJSON và chuyển đổi các giá trị lan / lot, vì định dạng GeoJSON sử dụng thứ tự tọa độ lon / lat. Tôi đã sử dụng một vòng lặp cho nhiệm vụ này.
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);
}
Bây giờ tôi đã có một mảng tọa độ được sắp xếp chính xác, tôi có thể tạo một tính năng đa tuyến, đây là đầu vào hợp lệ duy nhất L.animatedMarker
theo như tôi biết.
var coords = L.polyline(raw),
animatedMarker = L.animatedMarker(coords.getLatLngs(), {
distance: 100,
interval: 2500,
autoStart: false
});
Các tùy chọn distance
và interval
xác định tốc độ của điểm đánh dấu trên dòng. Bạn phải tinh chỉnh nó, để video của bạn sẽ kết thúc cùng lúc với điểm đánh dấu của bạn. Tôi cũng phải đặt autoStart
tùy chọn thành false
, vì vậy sau này tôi có thể bắt đầu đánh dấu bằng video.
Từ bây giờ, đây là phần "ma thuật". Nếu bạn muốn có quyền kiểm soát đồng thời video và điểm đánh dấu của mình, bạn phải sử dụng API trang web yêu thích của mình bên cạnh Leaflet. Trong ví dụ này, tôi đã sử dụng khung Froogaloop của Vimeo. Nếu bạn muốn nhúng video từ YouTube, bạn phải tìm kiếm cách bạn có thể sử dụng API của nó cho nhiệm vụ này. Trong bước tiếp theo, tôi đã thêm L.popup
lớp và liên kết nó với điểm đánh dấu.
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&byline=0&portrait=0&autoplay=0&api=1&player_id=player1" width="200" height="150" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>');
animatedMarker.bindPopup(popup).openPopup();
Tùy chọn quan trọng nhất trong đối tượng này là nội dung. Bạn phải thêm ID vào iframe
thẻ và đưa nó vào liên kết của video, theo yêu cầu &player_id=player1
. Bạn cũng phải bao gồm yêu cầu sử dụng API của Vimeo với &api=1
.
Tôi đã sử dụng một mã mẫu để viết trình nghe sự kiện cho các video. Mã mẫu được sử dụng JQuery, tôi và tôi sẽ chỉ chi tiết phần tùy chỉnh của mã.
player.addEvent('ready', function() {
player.addEvent('pause', onPause);
player.addEvent('finish', onFinish);
player.addEvent('play', onPlay);
player.addEvent('seek', onSeek);
});
Chúng tôi sẽ cần bốn sự kiện từ video. Chúng ta phải biết nếu nó bị tạm dừng ( pause
), nếu nó kết thúc ( finish
), nếu nó đang phát ( play
) hoặc nếu chúng ta nhảy vào video ( seek
). Thận trọng: không sử dụng playProgress
sự kiện để liên kết với animatedMarker.start()
nó, nó sẽ khiến điểm đánh dấu tăng tốc không kiểm soát. Bây giờ để tạo các chức năng thích hợp cho các sự kiện.
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);
}
Ba sự kiện đầu tiên sẽ trả về một chức năng để bắt đầu hoặc dừng điểm đánh dấu trên dòng nếu video đã được bắt đầu hoặc dừng. Sự kiện thứ tư là một chút khác nhau. Để di chuyển điểm đánh dấu trên bản đồ bằng video, chúng tôi phải sử dụng công thức để thiết lập địa điểm mới của người đánh dấu trên bản đồ. Vị trí hiện tại của dấu (đỉnh trong đa tuyến) được lưu trữ trong marker._i
thuộc tính nếu biến của bạn L.animatedMarker
được gọi marker
. May mắn thayseek
sự kiện trả về một đối tượng có thời lượng, vị trí và tỷ lệ phần trăm được phát của video (theo tỷ lệ từ 0 đến 1). Nếu chúng ta trả lại đỉnh gần nhất với số đỉnh được nhân với tỷ lệ phần trăm mong muốn của video và làm tròn nó đến số nguyên gần nhất, chúng ta sẽ có được vị trí đánh dấu trên dòng trong thời điểm mong muốn của video với xấp xỉ tốt. Bạn có thể tối ưu hóa độ chính xác của phương pháp này bằng cách tạo thời lượng chuyển động của người đánh dấu miễn là video và hoạt động với nhiều điểm (tất nhiên nó chỉ hoạt động tốt nếu các đỉnh được phân bổ đều trên đường thẳng).
Tôi hy vọng câu trả lời này sẽ giúp ích và xin lỗi cho tiếng Anh của tôi.
CẬP NHẬT:
Nếu bạn muốn điểm đánh dấu của mình tuân theo chỉ dẫn của bạn khi video bị tạm dừng, bạn sẽ không thể sử dụng L.animatedMarker.update()
. Bạn phải sử dụng L.animatedMarker.start()
và L.animatedMarker.stop()
điều này sẽ khiến điểm đánh dấu nhảy qua một đỉnh. Thật không may, điều này sẽ làm giảm độ chính xác của hình ảnh động, nhưng đây là cái giá bạn phải trả cho một bản đồ tương tác (cho đến khi tác giả sửa chữa L.animatedMarker.update()
chức năng).