Bản đồ vector tương tác của Nga JQVMap. Ya.Maps và SVG

Bây giờ chúng ta sẽ từng bước tìm ra cách làm cho bất kỳ hình ảnh nào trên trang web có tính tương tác, nghĩa là có thể chọn tất cả các phần của hình ảnh bằng cách di chuột và nhấp vào chúng. Ví dụ về loại hình ảnh này có thể là ảnh trên các trang web bất động sản, các trang web có bản đồ nơi bạn có thể nhấp vào các phần của chúng để chuyển đến trang khác hoặc để khởi chạy. hành động nhất định hoặc để bật hoạt ảnh trên trang web. Hãy bắt đầu nào!

BƯỚC 1. Chuẩn bị đánh dấu HTML cơ bản

Thêm mã dưới đây:

Sau khi thêm mã này, đừng lo lắng nếu bạn không thấy ảnh mà mình đã kết nối. Cuộn trang xuống một chút, nó sẽ ở đó. Hình ảnh bạn đưa vào đã bị di chuyển xuống do phần tử svg đã được thêm vào phía trước nó. Chúng tôi đã viết ra kích thước của bức tranh của chúng tôi trong đó và bây giờ nó chiếm cùng một không gian với ảnh gốc. Ghi chú: Trong thuộc tính viewBox của phần tử svg, bạn cần chỉ định kích thước hình ảnh mà bạn sẽ tạo
tương tác.

BƯỚC 2. Tạo các phần tử SVG

công việc tiếp theo bạn cần cài đặt một chương trình cho phép bạn làm việc với đồ họa svg Inkscape. Sau khi cài đặt chương trình, bạn có thể chạy nó. Mở hình ảnh của bạn trong chương trình này trong tab “tệp” và “mở…”. Trong trường hợp của tôi, đây là hình ảnh của bản đồ thế giới. Sau đó bấm vào nút ở góc dưới bên phải “Xem và chỉnh sửa XML“. Sau khi nhấp vào nút này, tiện ích tương ứng sẽ xuất hiện ở bên phải màn hình.

Sau khi chọn, hãy chọn dòng xuất hiện của phần hình ảnh bạn đã chọn trong trình chỉnh sửa xml. Sau đó chọn trường d của phần tử này và sao chép nội dung của nó thấp hơn một chút.

Trường d sẽ chứa một lượng tọa độ khá lớn. Sao chép và dán tất cả những thứ này trong mã HTML của bạn vào thuộc tính d của thành phần đường dẫn.

Sau khi thêm tọa độ, bạn có thể làm mới trang. Bạn sẽ thấy hình chiếu màu đen của hình ảnh mà bạn vẽ trước đó đã xuất hiện.

BƯỚC 3. Thêm kiểu

Để toàn bộ nội dung này được hiển thị bình thường, chúng ta cần thêm các kiểu sau vào các phần tử của mình:

Bản đồ ( vị trí: tương đối; căn chỉnh văn bản: giữa; ) đường dẫn svg ( vị trí: tuyệt đối; trên cùng: 0; trái: 0; chiều cao: 100%; chiều rộng: 100%; ) đường dẫn ( độ mờ: 0,4; điền: màu cam; con trỏ: con trỏ; chuyển tiếp: 0,3 giây; ) đường dẫn: di chuột ( độ mờ: 0,8; chuyển tiếp: 0,3 giây; )

Tùy thuộc vào loại hình ảnh bạn sử dụng, bạn sẽ có một chút loại khác Hình ảnh. Ví dụ, đây là cách nó xảy ra với tôi. Tôi đã vẽ các đường viền của bức tranh khá quanh co, nhưng đối với tôi, điều chính yếu là thể hiện những gì xuất hiện cuối cùng) Tôi đã không làm cho toàn bộ bản đồ trở nên tương tác và chính xác hơn vì nó sẽ mất nhiều thời gian hơn, nhưng kết quả sẽ đã giống nhau. Điều chính là bạn hiểu cách thức hoạt động và cách thực hiện nó.

Ghi chú: Bạn có thể thêm liên kết đến các hình ảnh tương tác như vậy, kết nối kịch bản khác nhauđể tăng cường chức năng tổng thể. Bạn không bị giới hạn trong trí tưởng tượng của mình.

Tất cả! Bây giờ bạn đã thực hiện lần đầu tiên svg tương tác bản đồ.

  • Hướng dẫn

Hãy tạo một bản đồ tương tác. Thứ gì đó. Tương tác nghĩa là gì? Chà, nó cần tương tác với người dùng và dữ liệu trên trang web mà nó đang truy cập. Tôi nghĩ điều này là đủ để coi nó có tính tương tác.

Vâng, hãy lấy SVG. Tại sao? Có, bởi vì nó dễ dàng làm việc đối với người đã quen với HTML. SVG là định dạng vectơ, dựa trên XML. Nghĩa là, một hình ảnh SVG có DOM riêng, các quy tắc CSS có thể được áp dụng cho nhiều phần tử khác nhau và được kiểm soát bởi JavaScript cũ.

Vậy chúng ta bắt đầu nhé?

Những người thiếu kiên nhẫn nhất có thể xem bản demo ngay lập tức, nhưng tôi khuyên bạn nên đọc mọi thứ theo thứ tự.

Chuẩn bị bản đồ Đầu tiên, chúng ta cần bản chất. Đó là, bản thân thẻ. Nếu Google không trợ giúp thì bạn có thể tự vẽ, mặc dù điều đó không khó thực hiện trong Inkscape.

Ví dụ: tôi sẽ lấy bản đồ của một quốc gia (nguồn trên Wikimedia Commons)

Vì theo kế hoạch của tôi, các khu vực trên bản đồ không được có các màu khác nhau, nên trước tiên tôi cắt các kiểu tô màu và nét vẽ khỏi các thẻ mà tôi quan tâm, nhưng đổi lại tôi cung cấp cho các phần tử này lớp và id mà tôi cần. Ví dụ: class="area" dành cho vùng và class="city" dành cho thành phố.

Tiếp theo, trong phần hình ảnh, chúng tôi đặt những thứ quen thuộc đến đau lòng:
.area ( nét: đen; chiều rộng nét: 2px; tô: #E9FFE9; ) .city ( nét: đen; chiều rộng nét: 2px; tô: đỏ; )
Đây là CSS mà tôi đã hứa trong thực tế. Về nguyên tắc, điều này là đủ. Khác biệt.

Kết quả:

Chèn SVG vào HTML Quá trình này đã được đề cập đầy đủ chi tiết trong tài liệu habratopic Về vấn đề sử dụng SVG trên nhiều trình duyệt.

Chúng ta sẽ sử dụng HTML5 và sử dụng cách đơn giản nhất, nhân văn nhất và chuẩn nhất:

Tất cả các trình duyệt hỗ trợ SVG sẽ “ăn” nó một cách chính xác và hiển thị nó. Và họ thậm chí sẽ cho chúng tôi làm việc với anh ấy. Trong một điều kiện: nếu máy chủ web phục vụ nó với loại MIME image/svg+xml. Một loại MIME khác có thể rất khó hiểu Google Chrome(nhưng không phải Opera, vốn biết chắc chắn từ thẻ rằng nó đang tuân theo SVG và không nhượng bộ trước những hành động khiêu khích).

Thứ hai phương pháp đúng- chèn mã SVG trực tiếp vào HTML. Tuyệt vời từ quan điểm kịch bản, nhưng hỗ trợ trình duyệt vẫn còn tệ hơn. Nhân tiện, hãy lưu ý rằng SVG được chèn vào HTML “tự do” vẫn còn là XML “khắc nghiệt”, vì vậy cần có dấu ngoặc kép và thẻ đóng.

Cào dưới nước Nhưng không phải mọi thứ đều đơn giản như vậy. Bạn có thể nhận thấy ngay rằng các trình duyệt nhất quyết không muốn chia tỷ lệ bản đồ của chúng tôi và nếu nó không vừa, thì chúng sẽ hiển thị các thanh cuộn, như thế này:

Để trình duyệt hoạt động với SVG theo cách chúng ta mong đợi, chúng ta nên xóa thuộc tính chiều rộng và chiều cao khỏi thẻ trong tệp SVG (hoặc đặt chúng thành 100%) và chèn thuộc tính viewBox được thiết kế đặc biệt cho trình duyệt có giá trị cho tọa độ của góc ảnh trên bên trái và góc dưới bên phải:
viewBox="0 0 493 416" Khác biệt .

Sau đó, tình hình được cải thiện đáng kể, nhưng Google Chrome lại mang đến cho chúng ta một điều thú vị khác: nó kiên trì cố gắng điều chỉnh tỷ lệ hình ảnh theo chiều cao của phần tử và không tăng chiều cao theo chiều rộng của thẻ và tỷ lệ của hình ảnh , như các trình duyệt khác hoạt động.


Thật đáng tiếc. Bạn sẽ phải sử dụng JavaScript và điều chỉnh chiều cao của phần tử theo cách thủ công.
var viewBox = svgdom.rootElement.getAttribution("viewBox").split(" "); var khía cạnhRatio = viewBox/viewBox; svgobject.height = phân tích cú phápInt(svgobject.offsetWidth / khía cạnhRatio); Khác biệt.

Kết quả:

Tương tác với SVG Chúng ta không cần bất cứ thứ gì để tương tác với SVG được viết trực tiếp vào HTML - nó đã là một phần của DOM của trang web.

Việc truy cập các SVG được chèn qua sẽ khó khăn hơn một chút:
jQuery(window).load(function () ( // Chúng ta cần đợi cho đến khi tất cả đồ họa (và cả bản đồ của chúng ta) được tải, vì vậy chúng ta sử dụng window.onload, var svgobject = document.getElementById("svgmap"); / / Tìm thẻ if ("contentDocument" in svgobject) ( // Chúng ta thực sự có thứ gì ở đó không? var svgdom = jQuery(svgobject.contentDocument); // Access mô hình đối tượng Tệp SVG // Bây giờ chúng tôi thực hiện công việc của mình, ví dụ: jQuery("#figure1", svgdom).attr("fill", "red"); // Tìm thẻ có id="figure1" trong SVG DOM và tô màu đỏ ) ));
Có, jQuery hoạt động với SVG nhưng chỉ một phần. Ví dụ: tôi nhận thấy rằng các hàm addClass và RemoveClass cũng như tìm kiếm lớp (jQuery(".class") không hoạt động. Chúng ta phải biến thái.

Lưu ý rằng tôi đang sử dụng sự kiện window.onload vì chúng tôi cần đợi hết chỗ các trang, cùng với tất cả các yếu tố liên quan (bao gồm cả bản đồ của chúng tôi). Tuy nhiên, ở đây Google Chrome cũng vội vàng làm khó chúng tôi: nếu tập lệnh có window.onload nằm trong mã html trước thẻ thì mã trong trình xử lý sẽ được thực thi TRƯỚC KHI bản đồ thực sự được tải. Vì vậy, thẻ phải được đặt sau bản đồ của chúng tôi. Đáng buồn nhưng là sự thật.

Tương tác thứ nhất: chọn các khu vực trên bản đồ bằng cách nhấp vào hộp kiểm trên trang. Đối với tương tác này, chúng tôi sẽ cần các hộp kiểm trong mỗi hàng của bảng với các khu vực, cũng như các id trùng khớp hoặc tương tự cho các hàng của bảng và các khu vực trên bản đồ.

Tại đây, khi bạn nhấp vào hộp kiểm, chúng tôi sẽ đặt hoặc xóa lớp đã chọn khỏi khu vực tương ứng trên bản đồ và khỏi chính dòng đó. Nó không khó:
$("#areas input").change(function() ( var row = $(this).parent().parent(); var id = row.attr("id"); if (this.checked) ( row.addClass("selected"); $("#"+id, svgdom).myAddClass("selected"); else ( row.removeClass("selected"); $("#"+id, svgdom). myRemoveClass ("đã chọn");
Theo đó, bạn cần thêm định nghĩa style cho lớp này. Tôi để bạn tự làm việc này, tùy theo sở thích và sở thích của bạn. Khác biệt.

Tính tương tác thứ hai: chúng tôi mở/hiển thị tên trên bản đồ bằng cách nhấp vào hộp kiểm trên trang. Sự tương tác này thậm chí còn được thực hiện dễ dàng hơn. Chúng tôi chèn một ít JavaScript vào trang để thêm/xóa lớp ẩn (khả năng hiển thị: ẩn;) đối với tất cả các thành phần được liên kết với tên trên bản đồ:
$("#titleswitch").change(function () ( var Elements = $(svgdom.getElementsByClassName("areatitle")) .add($(svgdom.getElementsByClassName("citytitle"))) .add($(svgdom. getElementsByClassName("titlebox"))) .add($(svgdom.getElementsByClassName("titleline"))); if (this.checked) ( Elements.myAddClass("hidden"); ) else ( Elements.myRemoveClass("hidden" ); ) ));
Như thế này .

Tương tác thứ ba: đánh dấu các khu vực trên bản đồ khi bạn di chuột qua một hàng trong bảng (và ngược lại). Để thực hiện việc này, bạn cần treo các trình xử lý sự kiện onhover như trên một bảng:
// Đánh dấu vùng trên bản đồ khi bạn di chuột qua vùng tương ứng. hàng bàn. $("#areas tr").hover(function () ( var id = $(this).attr("id"); $("#"+id, svgdom).myAddClass("highlight"); ), function () ( var id = $(this).attr("id"); $("#"+id, svgdom).myRemoveClass("highlight"); ));
...và tới các khu vực trên bản đồ:
// Đánh dấu một hàng trong bảng khi bạn di chuột qua hàng tương ứng. khu vực trên bản đồ $(svgdom.getElementsByClassName("area")).hover(function () ( var id = $(this).attr("id"); $("#areas #"+id).addClass( " highlight"); ), hàm () ( var id = $(this).attr("id"); $("#areas #"+id).removeClass("highlight"); ));
Để chúng ta thấy điều này, chúng ta sẽ thêm các quy tắc CSS tương ứng vào trang:
tr.highlight, tr:hover, tr:nth-child(even):hover ( nền: light yellow; ) ...và tới bản đồ SVG: .highlight, .area:hover ( fill: light yellow; Stroke: black; )
Khi bạn di chuột qua một hàng của bảng (hoặc trên một khu vực trên bản đồ), lớp cần đánh dấu sẽ được thêm vào khu vực tương ứng trên bản đồ (trên hàng của bảng). Để đoạn mã trên hoạt động, các khu vực trên bản đồ và các hàng trong bảng phải có id giống nhau (hoặc tương tự). Khác biệt.

Tương tác thứ tư: Hiển thị dữ liệu từ một trang trên bản đồ Chà, việc phân công các lớp tầm thường có lẽ đã nhàm chán rồi. Hãy để bản đồ hiển thị cho chúng tôi một số dữ liệu.

Điều đầu tiên trước tiên: dữ liệu. Hãy thêm một vài cột vào bảng của chúng ta, ví dụ như “People” và “Money”. Chú ý: Dữ liệu được lấy từ một kẻ ngốc và không liên quan gì đến Amestris thật. Và cả các nút radio mà chúng tôi sẽ sử dụng để chuyển đổi dữ liệu nào sẽ hiển thị.

Thứ hai, chúng ta cần một vị trí trên bản đồ nơi dữ liệu sẽ được hiển thị. Hãy thêm năm khối vào bản đồ (một khối cho mỗi vùng, tương ứng với id của chúng với các vùng) và các kiểu tương ứng trong:

Chà, mã JavaScript sẽ lấy dữ liệu từ các ô của bảng và đặt nó vào các khối văn bản:
$("input").change(function () ( var descnum = $(this).parent().prevAll().length+1; $("#areas tbody tr").each(function() ( var id = $(this).attr("id").substring(4); var value = $(this).children(":nth-child("+descnum+")").text(); +id, svgdom).text(giá trị); ) ));
Và bằng cách chuyển đổi các nút radio, thẻ sẽ hiển thị các số được yêu cầu. Thì đấy!

Tương tác thứ năm: chú giải công cụ Điều này có thể là quá nhiều, nhưng hãy để nó như vậy. Cho biện pháp tốt.

của sự tương tác này Hãy lấy plugin jQuery.tooltip và liên kết nó với các khu vực trên bản đồ. Tất nhiên, chúng tôi sẽ lấy văn bản cho các gợi ý từ bảng:
$(svgdom.getElementsByClassName("area")).tooltip(( bodyHandler: function() ( var id = $(this).attr("id"); var khu vực = $("#areas #"+id+" td :nth-child(2)").text(); var result = $("

").append($("").text(area)); $("#areas #"+id+" td:nth-child(2)").nextAll().each(function())( var pos = $(this).prevAll().length+1; var title = $("#areas thead th:nth-child("+pos+")").text(); văn bản (); result.append($("

").text(title + ": " + value)); )); kết quả trả về; ) ));


Khác biệt.

Và vân vân... Tất nhiên, khả năng tương tác với SVG không bị giới hạn ở điều này. Bạn có thể làm bất cứ việc gì. Xáo trộn DOM, thay đổi trang và SVG bằng cách sử dụng các yêu cầu AJAX và nhiều hơn thế nữa. Đi cho nó.
Những cạm bẫy còn lại từ vấn đề đã biết Hiện tại, có thể lưu ý rằng Google Chrome không in hình ảnh SVG. Đây có thể là lỗi của nó hoặc lỗi của WebKit nói chung. trình duyệt hiện đại hỗ trợ SVG: IE 9+, Opera 8+, Firefox 3+ (Firefox 1.5+ có hỗ trợ một phần), Chrome tất cả các phiên bản, Safari 3.2+ (danh sách đầy đủ hơn)

Nhưng than ôi, tương lai tươi sáng vẫn chưa đến và chúng ta vẫn phải nghĩ đến việc hỗ trợ các trình duyệt cũ.

Cách tiêu chuẩn và dễ dàng nhất nếu SVG chỉ là hình ảnh: chèn nội dung thay thế (được hiển thị ở dạng Hình ảnh PNG và một đoạn văn bản) bên trong thẻ.

Xin lỗi, bạn đang sử dụng Phiên bản lỗi thời trình duyệt không hỗ trợ bản đồ tương tác.


Nếu trình duyệt không hỗ trợ SVG, hình ảnh và văn bản PNG sẽ được hiển thị để thông báo cho người dùng rằng trình duyệt của họ đã lỗi thời. Không có tính tương tác. Tuy nhiên, nó có thể không thực sự cần thiết. Đúng, có một nhược điểm - như tôi nhận thấy, các trình duyệt hiện đại cố tình tải xuống hình ảnh png thay thế, mặc dù thực tế là chúng vẫn không hiển thị nó.

Những người quan tâm có thể tận dụng tính năng phát hiện hỗ trợ SVG bằng Modernizr và tạo thứ gì đó phức tạp hơn trong JavaScript.

Đối với các trường hợp phức tạp hơn, nhiều giải pháp sử dụng Flash, VML hoặc Canvas (hoặc tất cả chúng) có thể giúp bạn. Bạn có thể tìm thấy danh sách ở đây: HTML5 Crossbrowser Polyfills, nhưng thật không may, các giải pháp mà tôi đã thử không giúp được gì cho tôi. Có lẽ bởi vì SVG với CSS mà tôi phác họa trên đầu gối hóa ra lại quá khó đối với họ.

Chuyển đổi SVG sang PNG Có nhiều nơi trực tuyến nơi bạn có thể chuyển đổi hình ảnh SVG sang một hình ảnh khác. Tôi sẽ đề xuất sử dụng lệnh rsvg-convert từ gói librsvg2-bin. Một cái gì đó như thế này:
bản đồ mèo.svg | rsvg-convert > map.png
Tuy nhiên, nó có thể chuyển đổi sang các định dạng khác, cũng như phóng to/thu nhỏ hình ảnh, xem --help.
Để chuyển đổi hàng loạt, bạn có thể tạo lệnh phức tạp hơn hoặc xem ví dụ trong Thêm thẻ
  • Hướng dẫn

Hãy tạo một bản đồ tương tác. Thứ gì đó. Tương tác nghĩa là gì? Chà, nó cần tương tác với người dùng và dữ liệu trên trang web mà nó đang truy cập. Tôi nghĩ điều này là đủ để coi nó có tính tương tác.

Vâng, hãy lấy SVG. Tại sao? Có, bởi vì nó dễ dàng làm việc đối với người đã quen với HTML. SVG là một định dạng vector dựa trên XML. Nghĩa là, một hình ảnh SVG có DOM riêng, các quy tắc CSS có thể được áp dụng cho nhiều thành phần khác nhau và được kiểm soát bởi JavaScript cũ.

Vậy chúng ta bắt đầu nhé?

Những người thiếu kiên nhẫn nhất có thể xem bản demo ngay lập tức, nhưng tôi khuyên bạn nên đọc mọi thứ theo thứ tự.

Chuẩn bị bản đồ Đầu tiên, chúng ta cần bản chất. Đó là, bản thân thẻ. Nếu Google không trợ giúp thì bạn có thể tự vẽ, mặc dù điều đó không khó thực hiện trong Inkscape.

Ví dụ: tôi sẽ lấy bản đồ của một quốc gia (nguồn trên Wikimedia Commons)

Vì theo kế hoạch của tôi, các khu vực trên bản đồ không được có các màu khác nhau, nên trước tiên tôi cắt các kiểu tô màu và nét vẽ khỏi các thẻ mà tôi quan tâm, nhưng đổi lại tôi cung cấp cho các phần tử này lớp và id mà tôi cần. Ví dụ: class="area" dành cho vùng và class="city" dành cho thành phố.

Tiếp theo, trong phần hình ảnh, chúng tôi đặt những thứ quen thuộc đến đau lòng:
.area ( nét: đen; chiều rộng nét: 2px; tô: #E9FFE9; ) .city ( nét: đen; chiều rộng nét: 2px; tô: đỏ; )
Đây là CSS mà tôi đã hứa trong thực tế. Về nguyên tắc, điều này là đủ. Khác biệt.

Kết quả:

Chèn SVG vào HTML Quá trình này đã được đề cập đầy đủ chi tiết trong tài liệu habratopic.

Chúng ta sẽ sử dụng HTML5 và sử dụng cách đơn giản nhất, nhân văn nhất và chuẩn nhất:

Tất cả các trình duyệt hỗ trợ SVG sẽ “ăn” nó một cách chính xác và hiển thị nó. Và họ thậm chí sẽ cho chúng tôi làm việc với anh ấy. Trong một điều kiện: nếu máy chủ web phục vụ nó với loại MIME image/svg+xml. Một loại MIME khác có thể gây nhầm lẫn rất nhiều cho Google Chrome (nhưng không phải Opera, vốn biết chắc chắn từ thẻ rằng nó theo sau SVG và không nhượng bộ trước những hành động khiêu khích).

Phương pháp đúng thứ hai là chèn mã SVG trực tiếp vào HTML. Tuyệt vời từ quan điểm kịch bản, nhưng hỗ trợ trình duyệt vẫn còn tệ hơn. Nhân tiện, hãy lưu ý rằng SVG được chèn vào HTML “tự do” vẫn còn là XML “khắc nghiệt”, vì vậy cần có dấu ngoặc kép và thẻ đóng.

Cào dưới nước Nhưng không phải mọi thứ đều đơn giản như vậy. Bạn có thể nhận thấy ngay rằng các trình duyệt nhất quyết không muốn chia tỷ lệ bản đồ của chúng tôi và nếu nó không vừa, thì chúng sẽ hiển thị các thanh cuộn, như thế này:

Để trình duyệt hoạt động với SVG theo cách chúng ta mong đợi, chúng ta nên xóa thuộc tính chiều rộng và chiều cao khỏi thẻ trong tệp SVG (hoặc đặt chúng thành 100%) và chèn thuộc tính viewBox được thiết kế đặc biệt cho trình duyệt có giá trị cho tọa độ của góc ảnh trên bên trái và góc dưới bên phải:
viewBox="0 0 493 416" Khác biệt .

Sau đó, tình hình được cải thiện đáng kể, nhưng Google Chrome lại mang đến cho chúng ta một điều thú vị khác: nó kiên trì cố gắng điều chỉnh tỷ lệ hình ảnh theo chiều cao của phần tử và không tăng chiều cao theo chiều rộng của thẻ và tỷ lệ của hình ảnh , như các trình duyệt khác hoạt động.


Thật đáng tiếc. Bạn sẽ phải sử dụng JavaScript và điều chỉnh chiều cao của phần tử theo cách thủ công.
var viewBox = svgdom.rootElement.getAttribution("viewBox").split(" "); var khía cạnhRatio = viewBox/viewBox; svgobject.height = phân tích cú phápInt(svgobject.offsetWidth / khía cạnhRatio); Khác biệt.

Kết quả:

Tương tác với SVG Chúng ta không cần bất cứ thứ gì để tương tác với SVG được viết trực tiếp vào HTML - nó đã là một phần của DOM của trang web.

Việc truy cập các SVG được chèn qua sẽ khó khăn hơn một chút:
jQuery(window).load(function () ( // Chúng ta cần đợi cho đến khi tất cả đồ họa (và cả bản đồ của chúng ta) được tải, vì vậy chúng ta sử dụng window.onload, var svgobject = document.getElementById("svgmap"); / / Tìm thẻ if ("contentDocument" in svgobject) ( // Chúng ta thực sự có thứ gì ở đó không? var svgdom = jQuery(svgobject.contentDocument); // Truy cập mô hình đối tượng của tệp SVG // Bây giờ hãy thực hiện công việc của chúng ta, ví dụ: jQuery ("#figure1", svgdom).attr("fill", "red"); // Tìm thẻ có id="figure1" trong SVG DOM và tô màu đỏ ) ));
Có, jQuery hoạt động với SVG nhưng chỉ một phần. Ví dụ: tôi nhận thấy rằng các hàm addClass và RemoveClass cũng như tìm kiếm lớp (jQuery(".class") không hoạt động. Chúng ta phải biến thái.

Lưu ý rằng tôi đang sử dụng sự kiện window.onload vì chúng tôi cần đợi trang tải đầy đủ, cùng với tất cả các thành phần liên quan (bao gồm cả bản đồ của chúng tôi). Tuy nhiên, ở đây Google Chrome cũng vội vàng làm khó chúng tôi: nếu tập lệnh có window.onload nằm trong mã html trước thẻ thì mã trong trình xử lý sẽ được thực thi TRƯỚC KHI bản đồ thực sự được tải. Vì vậy, thẻ phải được đặt sau bản đồ của chúng tôi. Đáng buồn nhưng là sự thật.

Tương tác thứ nhất: chọn các khu vực trên bản đồ bằng cách nhấp vào hộp kiểm trên trang. Đối với tương tác này, chúng tôi sẽ cần các hộp kiểm trong mỗi hàng của bảng với các khu vực, cũng như các id trùng khớp hoặc tương tự cho các hàng của bảng và các khu vực trên bản đồ.

Tại đây, khi bạn nhấp vào hộp kiểm, chúng tôi sẽ đặt hoặc xóa lớp đã chọn khỏi khu vực tương ứng trên bản đồ và khỏi chính dòng đó. Nó không khó:
$("#areas input").change(function() ( var row = $(this).parent().parent(); var id = row.attr("id"); if (this.checked) ( row.addClass("selected"); $("#"+id, svgdom).myAddClass("selected"); else ( row.removeClass("selected"); $("#"+id, svgdom). myRemoveClass ("đã chọn");
Theo đó, bạn cần thêm định nghĩa style cho lớp này. Tôi để bạn tự làm việc này, tùy theo sở thích và sở thích của bạn. Khác biệt.

Tính tương tác thứ hai: chúng tôi mở/hiển thị tên trên bản đồ bằng cách nhấp vào hộp kiểm trên trang. Sự tương tác này thậm chí còn được thực hiện dễ dàng hơn. Chúng tôi chèn một ít JavaScript vào trang để thêm/xóa lớp ẩn (khả năng hiển thị: ẩn;) đối với tất cả các thành phần được liên kết với tên trên bản đồ:
$("#titleswitch").change(function () ( var Elements = $(svgdom.getElementsByClassName("areatitle")) .add($(svgdom.getElementsByClassName("citytitle"))) .add($(svgdom. getElementsByClassName("titlebox"))) .add($(svgdom.getElementsByClassName("titleline"))); if (this.checked) ( Elements.myAddClass("hidden"); ) else ( Elements.myRemoveClass("hidden" ); ) ));
Như thế này .

Tương tác thứ ba: đánh dấu các khu vực trên bản đồ khi bạn di chuột qua một hàng trong bảng (và ngược lại). Để thực hiện việc này, bạn cần treo các trình xử lý sự kiện onhover như trên một bảng:
// Đánh dấu vùng trên bản đồ khi bạn di chuột qua vùng tương ứng. hàng bàn. $("#areas tr").hover(function () ( var id = $(this).attr("id"); $("#"+id, svgdom).myAddClass("highlight"); ), function () ( var id = $(this).attr("id"); $("#"+id, svgdom).myRemoveClass("highlight"); ));
...và tới các khu vực trên bản đồ:
// Đánh dấu một hàng trong bảng khi bạn di chuột qua hàng tương ứng. khu vực trên bản đồ $(svgdom.getElementsByClassName("area")).hover(function () ( var id = $(this).attr("id"); $("#areas #"+id).addClass( " highlight"); ), hàm () ( var id = $(this).attr("id"); $("#areas #"+id).removeClass("highlight"); ));
Để chúng ta thấy điều này, chúng ta sẽ thêm các quy tắc CSS tương ứng vào trang:
tr.highlight, tr:hover, tr:nth-child(even):hover ( nền: light yellow; ) ...và tới bản đồ SVG: .highlight, .area:hover ( fill: light yellow; Stroke: black; )
Khi bạn di chuột qua một hàng của bảng (hoặc trên một khu vực trên bản đồ), lớp cần đánh dấu sẽ được thêm vào khu vực tương ứng trên bản đồ (trên hàng của bảng). Để đoạn mã trên hoạt động, các khu vực trên bản đồ và các hàng trong bảng phải có id giống nhau (hoặc tương tự). Khác biệt.

Tương tác thứ tư: Hiển thị dữ liệu từ một trang trên bản đồ Chà, việc phân công các lớp tầm thường có lẽ đã nhàm chán rồi. Hãy để bản đồ hiển thị cho chúng tôi một số dữ liệu.

Điều đầu tiên trước tiên: dữ liệu. Hãy thêm một vài cột vào bảng của chúng ta, ví dụ như “People” và “Money”. Chú ý: Dữ liệu được lấy từ một kẻ ngốc và không liên quan gì đến Amestris thật. Và cả các nút radio mà chúng tôi sẽ sử dụng để chuyển đổi dữ liệu nào sẽ hiển thị.

Thứ hai, chúng ta cần một vị trí trên bản đồ nơi dữ liệu sẽ được hiển thị. Hãy thêm năm khối vào bản đồ (một khối cho mỗi vùng, tương ứng với id của chúng với các vùng) và các kiểu tương ứng trong:

Chà, mã JavaScript sẽ lấy dữ liệu từ các ô của bảng và đặt nó vào các khối văn bản:
$("input").change(function () ( var descnum = $(this).parent().prevAll().length+1; $("#areas tbody tr").each(function() ( var id = $(this).attr("id").substring(4); var value = $(this).children(":nth-child("+descnum+")").text(); +id, svgdom).text(giá trị); ) ));
Và bằng cách chuyển đổi các nút radio, thẻ sẽ hiển thị các số được yêu cầu. Thì đấy!

Tương tác thứ năm: chú giải công cụ Điều này có thể là quá nhiều, nhưng hãy để nó như vậy. Cho biện pháp tốt.

Đối với sự tương tác này, hãy sử dụng plugin jQuery.tooltip và liên kết nó với các khu vực trên bản đồ. Tất nhiên, chúng tôi sẽ lấy văn bản cho các gợi ý từ bảng:
$(svgdom.getElementsByClassName("area")).tooltip(( bodyHandler: function() ( var id = $(this).attr("id"); var khu vực = $("#areas #"+id+" td :nth-child(2)").text(); var result = $("

").append($("").text(area)); $("#areas #"+id+" td:nth-child(2)").nextAll().each(function())( var pos = $(this).prevAll().length+1; var title = $("#areas thead th:nth-child("+pos+")").text(); văn bản (); result.append($("

").text(title + ": " + value)); )); kết quả trả về; ) ));


Khác biệt.

Và vân vân... Tất nhiên, khả năng tương tác với SVG không bị giới hạn ở điều này. Bạn có thể làm bất cứ việc gì. Xáo trộn DOM, thay đổi trang và SVG bằng cách sử dụng các yêu cầu AJAX và nhiều hơn thế nữa. Đi cho nó.
Những cạm bẫy còn tồn tại Trong số các vấn đề đã biết cho đến nay, có thể lưu ý rằng Google Chrome không in hình ảnh SVG. Đây có thể là lỗi của nó hoặc lỗi WebKit nói chung. Hầu hết tất cả các trình duyệt hiện đại đều hỗ trợ SVG: IE 9+, Opera 8+, Firefox 3+ (Firefox 1.5+ có hỗ trợ một phần), Chrome tất cả các phiên bản, Safari 3.2+ (thêm) danh sách hoàn thành )

Nhưng than ôi, tương lai tươi sáng vẫn chưa đến và chúng ta vẫn phải nghĩ đến việc hỗ trợ các trình duyệt cũ.

Cách tiêu chuẩn và dễ dàng nhất, nếu SVG chỉ là một hình ảnh: chèn nội dung thay thế (hình ảnh được hiển thị PNG và một đoạn văn bản) bên trong thẻ.

Thật không may, bạn đang sử dụng phiên bản trình duyệt lỗi thời không hỗ trợ bản đồ tương tác.


Nếu trình duyệt không hỗ trợ SVG, hình ảnh và văn bản PNG sẽ được hiển thị để thông báo cho người dùng rằng trình duyệt của họ đã lỗi thời. Không có tính tương tác. Tuy nhiên, nó có thể không thực sự cần thiết. Đúng, có một nhược điểm - như tôi nhận thấy, các trình duyệt hiện đại cố tình tải xuống hình ảnh png thay thế, mặc dù thực tế là chúng vẫn không hiển thị nó.

Những người quan tâm có thể tận dụng tính năng phát hiện hỗ trợ SVG bằng Modernizr và tạo thứ gì đó phức tạp hơn trong JavaScript.

Đối với các trường hợp phức tạp hơn, nhiều giải pháp sử dụng Flash, VML hoặc Canvas (hoặc tất cả chúng) có thể giúp bạn. Bạn có thể tìm thấy danh sách ở đây: HTML5 Crossbrowser Polyfills, nhưng thật không may, các giải pháp mà tôi đã thử không giúp được gì cho tôi. Có lẽ bởi vì SVG với CSS mà tôi phác họa trên đầu gối hóa ra lại quá khó đối với họ.

Chuyển đổi SVG sang PNG Có nhiều nơi trực tuyến nơi bạn có thể chuyển đổi hình ảnh SVG sang một hình ảnh khác. Tôi sẽ đề xuất sử dụng lệnh rsvg-convert từ gói librsvg2-bin. Một cái gì đó như thế này:
bản đồ mèo.svg | rsvg-convert > map.png
Tuy nhiên, nó có thể chuyển đổi sang các định dạng khác, cũng như phóng to/thu nhỏ hình ảnh, xem --help.
Đối với các phép biến đổi hàng loạt, bạn có thể soạn một lệnh phức tạp hơn hoặc xem các ví dụ trong bản đồ tương tác của chuỗi diễn đàn Thêm thẻ


Tôi muốn có thể tự vẽ lên bản đồ bằng SVG.

Ý tưởng là thế này: Tôi tạo một lớp có kích thước bằng TOÀN BỘ bản đồ tỷ lệ hiện tại và sau đó vẽ trên lớp này, chuyển đổi các điểm địa lý thành các điểm ảnh.

Làm thế nào để làm điều đó nhiều nhất một cách đơn giản? Thông qua IOverlay hoặc ILayer, hoặc có thể có cái gì khác thuận tiện hơn?

","contentType:"text/html"),"proposeBody":("source:"

Tôi muốn có thể tự vẽ lên bản đồ bằng SVG.

Ý tưởng là thế này: Tôi tạo một lớp có kích thước bằng TOÀN BỘ bản đồ tỷ lệ hiện tại và sau đó vẽ trên lớp này, chuyển đổi các điểm địa lý thành các điểm ảnh.

Làm thế nào để làm điều này một cách dễ dàng nhất? Thông qua IOverlay hoặc ILayer, hoặc có thể có cái gì khác thuận tiện hơn?

Tôi muốn có thể tự vẽ lên bản đồ bằng SVG.

Ý tưởng là thế này: Tôi tạo một lớp có kích thước bằng TOÀN BỘ bản đồ tỷ lệ hiện tại và sau đó vẽ trên lớp này, chuyển đổi các điểm địa lý thành các điểm ảnh.

Làm thế nào để làm điều này một cách dễ dàng nhất? Thông qua IOverlay hoặc ILayer, hoặc có thể có cái gì khác thuận tiện hơn?

","contentType":text/html"),"authorId":20653410","slug":6812","canEdit":false,"canComment":false,"isBanned":false,"canPublish" :false,"viewType">cũ","isDraft":false,"isOnModeration":false,"isSubscriber":false,"commentsCount":9,"modificationDate":Thứ Năm 01 tháng 1 năm 1970 03:00:00 GMT +0000 (UTC)","showPreview":true,"approvedPreview":("source:"

Tôi muốn có thể tự vẽ lên bản đồ bằng SVG.

Ý tưởng là thế này: Tôi tạo một lớp có kích thước bằng TOÀN BỘ bản đồ tỷ lệ hiện tại và sau đó vẽ trên lớp này, chuyển đổi các điểm địa lý thành các điểm ảnh.

Làm thế nào để làm điều này một cách dễ dàng nhất? Thông qua IOverlay hoặc ILayer, hoặc có thể có cái gì khác thuận tiện hơn?

","html":Tôi muốn có thể tự mình vẽ lên bản đồ bằng SVG. ","contentType":text/html"),"proposedPreview":("source:"

Tôi muốn có thể tự vẽ lên bản đồ bằng SVG.

Ý tưởng là thế này: Tôi tạo một lớp có kích thước bằng TOÀN BỘ bản đồ tỷ lệ hiện tại và sau đó vẽ trên lớp này, chuyển đổi các điểm địa lý thành các điểm ảnh.

Làm thế nào để làm điều này một cách dễ dàng nhất? Thông qua IOverlay hoặc ILayer, hoặc có thể có cái gì khác thuận tiện hơn?

","html":Tôi muốn có thể tự mình vẽ lên bản đồ bằng SVG. ","contentType":text/html"),"titleImage":null,"tags":[("displayName:"API 1.x","slug":api-1-x","categoryId ">150000131","url":/blog/mapsapi??tag=api-1-x")],"isModerator":false,"commentsEnabled":true,"url: //blog/mapsapi/ 6812","urlTemplate":/blog/mapsapi/%slug%","fullBlogUrl":https://yandex.ru/blog/mapsapi","addCommentUrl":"/blog/createComment/mapsapi/6812" ,"updateCommentUrl":/blog/updateComment/mapsapi/6812","addCommentWithCaptcha":"/blog/createWithCaptcha/mapsapi/6812","changeCaptchaUrl":"/blog/api/captcha/new","putImageUrl": "/blog/image/put","urlBlog":/blog/mapsapi","urlEditPost":/blog/56a9a2b3b15b79e31e0d72f2/edit","urlSlug":/blog/post/generateSlug","urlPublishPost": "/blog/56a9a2b3b15b79e31e0d72f2/publish","urlUnpublishPost":"/blog/56a9a2b3b15b79e31e0d72f2/unpublish","urlRemovePost":/blog/56a9a2b3b15b79e31e0d72f2/removePost ","urlDraft":/blog/mapsapi/6 812/bản nháp", "urlDraftTemplate":/blog/mapsapi/%slug%/draft","urlRemoveDraft": //blog/56a9a2b3b15b79e31e0d72f2/removeDraft","urlTagSuggest":"/blog/api/suggest/mapsapi","urlAfterDelete": /blog/mapsapi","isAuthor":false,"subscribeUrl":/blog/api/subscribe/56a9a2b3b15b79e31e0d72f2","unsubscribeUrl":/blog/api/unsubscribe/56a9a2b3b15b79e31e0d72f2","urlEditPostPage":"/blog/ mapsapi/56a9a2b3b15b79e31e0d72f2/edit","urlForTranslate": //blog/post/translate","urlRelateIssue": //blog/post/updateIssue","urlUpdateTranslate":"/blog/post/updateTranslate","urlLoadTranslate": "/blog/post/loadTranslate","urlTranslationStatus":/blog/mapsapi/6812/translationInfo","urlRelatArticles":"/blog/api/similarArticles/mapsapi/6812","tác giả":("id": "20653410","uid":("value://20653410","lite":false,"hosted":false),,"bí danh":(),"login://shasoft","display_name": ( "name:"shasoft","avatar":("mặc định":"21493/20653410-939638","empty":false)),,"địa chỉ:" [email được bảo vệ]","defaultAvatar":21493/20653410-939638","imageSrc":https://avatars.mds.yandex.net/get-yapic/21493/20653410-939638/islands-middle","isYandexStaff": false),"originModificationDate":"1970-01-01T00:00:00.000Z","socialImage":("orig":("fullPath":https://avatars.mds.yandex.net/get-yablogs /47421/file_1456488726678/orig")))))">