Tôi có sử dụng <img>, <object> hoặc <embed> cho các tệp SVG không?


603

Tôi nên sử dụng <img>, <object>hoặc <embed>để tải các tệp SVG vào một trang theo cách tương tự như tải một jpg, gifhoặc png?

Mã cho mỗi để đảm bảo nó hoạt động tốt nhất có thể là gì? (Tôi đang thấy các tài liệu tham khảo bao gồm các mô phỏng hoặc chỉ ra các trình kết xuất SVG dự phòng trong nghiên cứu của tôi và không thấy trạng thái tốt của tài liệu tham khảo nghệ thuật).

Giả sử tôi đang kiểm tra hỗ trợ SVG với Modernizr và quay lại (có thể thực hiện thay thế bằng <img>thẻ đơn giản ) cho các trình duyệt không hỗ trợ SVG.



2
Về mặt lý thuyết, bạn cũng có thể có một <svg>từ mà bạn muốn tham khảo các SVG khác. Điều này có thể đạt được, ví dụ như sử dụng <image>.
phk

Câu trả lời:


636

Tôi có thể giới thiệu Primer SVG (được xuất bản bởi W3C), bao gồm chủ đề này: http://www.w3.org/Graphics/SVG/IG/resource/svgprimer.html#SVG_inTube

Nếu bạn sử dụng <object>thì bạn nhận được dự phòng raster miễn phí *:

<object data="your.svg" type="image/svg+xml">
  <img src="yourfallback.jpg" />
</object>

*) Chà, không hoàn toàn miễn phí, vì một số trình duyệt tải xuống cả hai tài nguyên, hãy xem gợi ý của Larry bên dưới để biết cách khắc phục điều đó.

Cập nhật 2014:

  • Nếu bạn muốn có một Svg không tương tác, hãy sử dụng <img>với các đoạn mã dự phòng thành phiên bản png (đối với IE cũ hơn và android <3). Một cách đơn giản và đơn giản để làm điều đó:

    <img src="your.svg" onerror="this.src='your.png'">.

    Điều này sẽ hoạt động giống như một hình ảnh GIF và nếu trình duyệt của bạn hỗ trợ hoạt hình khai báo (SMIL) thì chúng sẽ phát.

  • Nếu bạn muốn có một Svg tương tác, sử dụng <iframe>hoặc <object>.

  • Nếu bạn cần cung cấp cho các trình duyệt cũ khả năng sử dụng plugin svg, thì hãy sử dụng <embed>.

  • Đối với svg trong css background-imagevà các thuộc tính tương tự, Modernizr là một lựa chọn để chuyển sang hình ảnh dự phòng, một tùy chọn khác phụ thuộc vào nhiều nền để thực hiện tự động:

    div {
        background-image: url(fallback.png);
        background-image: url(your.svg), none;
    }

    Lưu ý : chiến lược nhiều nền không hoạt động trên Android 2.3 vì nó hỗ trợ nhiều nền nhưng không phải là Svg.

Một bài đọc tốt khác là blogpost này về các dự phòng của Svg.


7
Cách đúng để đặt kích thước là gì? Tôi có bao gồm các thuộc tính chiều cao và chiều rộng hay tôi sử dụng CSS?
artlung

5
Sử dụng css là tốt hoặc đặt kích thước cho phần tử nhúng (nghĩa là: một trong hai iframe, nhúng, đối tượng, img) - những gì sau này có thể tránh được nội dung flash-of-unstyled trước biểu định kiểu xác định kích thước Nó đã nạp đầy. Ngoài ra, hãy đảm bảo rằng svg có thuộc tính viewBox và loại bỏ các thuộc tính width / height khỏi phần tử gốc svg. Điều đó sẽ cung cấp cho bạn các hành vi lai tốt nhất trong kinh nghiệm của tôi.
Erik Dahlström

8
Phương pháp này sẽ luôn tải tập tin raster. Câu trả lời này đảm bảo rằng dự phòng chỉ được yêu cầu trên các trình duyệt IE cũ.
Larry

3
Lưu ý rằng phần trên không hoạt động với Trình cắm Adobe SVG. Nhưng, bạn có thể làm cho tất cả hoạt động (trình duyệt hiện đại + ASV + MSIE) nếu bạn thêm <param name="src" value="your.svg" />vào bên trong <object>thẻ. Tôi đã dành một khoảng thời gian rất dài để cố gắng tìm ra cách để làm tất cả những điều đó, và tôi nghĩ rằng cuối cùng tôi đã có được nó.
Christopher Schultz

5
Tôi nghĩ rằng những người nhanh hơn ngừng hỗ trợ các trình duyệt cổ xưa thì chúng ta sẽ có một xã hội luôn cập nhật trình duyệt của họ, thậm chí sẽ tự động đi với trình duyệt từ năm 2012. Lý do duy nhất là không có quyền truy cập miễn phí vào trình duyệt hiện đại, nhưng Firefox ví dụ: vẫn hỗ trợ Windows XP (có thể là phiên bản 52). Luôn luôn có một sự thay thế hiện đại và miễn phí.
Sơ sinh

117

Từ IE9 trở lên, bạn có thể sử dụng SVG trong thẻ IMG thông thường ..

https://caniuse.com/svg-img

<img src="/static/image.svg">

35
Điều này không hoạt động nếu SVG yêu cầu các tài nguyên khác được tải. (Phông chữ, hình ảnh, ...)
TheHippo

11
Đối với logo hoặc biểu tượng, tôi vẫn khuyên bạn nên sử dụng thẻ IMG vì lý do ngữ nghĩa và đảm bảo rằng SVG chỉ là một minh họa vector.
Christian Landgren

4
Bây giờ được chấp nhận ở khắp mọi nơi. @artlung, bạn có thể muốn thay đổi câu trả lời của bạn cho câu hỏi này.
SteeveDroz

16
Bất cứ ai sử dụng <img/>thẻ đều có thể muốn biết về việc gắn thêm số nhận dạng phân mảnh SVG , ví dụ " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", cho phép bạn kiểm soát tỷ lệ khung hình viewBox, v.v., giống như với các định nghĩa SVG nội tuyến. Đọc thêm về nhân rộng - css-tricks.com/scale-svg
brichins

101

<object><embed>có một thuộc tính thú vị: họ cho phép lấy tài liệu tham khảo tài liệu SVG từ tài liệu bên ngoài (có chính sách cùng nguồn gốc). Tham chiếu sau đó có thể được sử dụng để làm động SVG, thay đổi biểu định kiểu, v.v.

Được

<object id="svg1" data="/static/image.svg" type="image/svg+xml"></object>

Sau đó bạn có thể làm những việc như

document.getElementById("svg1").addEventListener("load", function() {
    var doc = this.getSVGDocument();
    var rect = doc.querySelector("rect"); // suppose our image contains a <rect>
    rect.setAttribute("fill", "green");
});

Tôi không nghĩ rằng bạn sẽ nhận được một sự kiện "tải" từ một phần tử <object>. Không được hỗ trợ.
Steve O'Connor

5
@ SteveO'Connor Tôi không biết, có thể nó không được ghi chép tốt, nhưng nó chắc chắn hoạt động trong Firefox, IE11 và Chrome. Ít nhất là với các tệp SVG bên ngoài: Tôi không thể làm cho nó hoạt động với các URI dữ liệu.
WGH

Hoạt động tuyệt vời! Thật thú vị, việc thêm trường 'id' dường như là bắt buộc khi bạn có hai tệp SVG, nếu không thì chỉ có 1 sẽ hiển thị trong trình duyệt opera của tôi?
Bram

Bạn có được tốt nhất của cả nội tuyến và được tham chiếu với phương pháp này!
Brandito

Thật tốt khi biết rằng các siêu liên kết bên trong một SVG sẽ không hoạt động trừ khi SVG là nội tuyến.
Mentalist

26

Tùy chọn tốt nhất là sử dụng hình ảnh SVG trên các thiết bị khác nhau :)

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">

3
hấp dẫn. Nhưng bạn có yên tâm khi onerrorđám cháy xảy ra nếu svg không kết xuất? Những trình duyệt nào bạn đã thử nghiệm?
artlung

1
Có, tôi đã thử nghiệm nó trên HĐH Android di động, trình duyệt mặc định :)
Roberth Solís

24

Sử dụng srcset

Hầu hết các trình duyệt hiện nay đều hỗ trợ srcsetthuộc tính , cho phép chỉ định các hình ảnh khác nhau cho những người dùng khác nhau. Ví dụ: bạn có thể sử dụng nó cho mật độ pixel 1x và 2x và trình duyệt sẽ chọn đúng tệp.

Trong trường hợp này, nếu bạn chỉ định một SVG trong srcsetvà trình duyệt không hỗ trợ nó, nó sẽ dự phòng src.

<img src="logo.png" srcset="logo.svg" alt="My logo">

Phương pháp này có một số lợi ích so với các giải pháp khác:

  1. Nó không dựa vào bất kỳ hack hay kịch bản kỳ lạ nào
  2. Nó đơn giản
  3. Bạn vẫn có thể bao gồm văn bản thay thế
  4. Các trình duyệt hỗ trợ srcsetnên biết cách xử lý để nó chỉ tải xuống tệp mà nó cần.

5
Tại sao phải bận tâm vì có> 99% cơ hội rằng bất kỳ trình duyệt nào sẽ hỗ trợ SVG trong những ngày này?
Robert Longson

5
Một phần từ việc đảm bảo MỌI NGƯỜI có thể xem trang chính xác, Google sẽ yêu bạn nhiều hơn!
Hoots

2
Có vẻ tốt hơn so với thực tế, tại thời điểm hiện tại bạn đang đẩy hình ảnh dự phòng xuống ~ 10% người dùng.
Volker E.

2
@VolkerE. 10%? caniuse cho thấy thiếu hỗ trợ SVG khoảng 2% . Tôi vẫn sử dụng srcset như trong câu trả lời mặc dù để hỗ trợ 2%. Trong tương lai, tôi hy vọng các trình duyệt có thể lấy thông tin như srcset và chọn hình ảnh phù hợp dựa trên các yếu tố như hiệu suất và kích thước, không chỉ hỗ trợ kích thước thiết bị hoặc định dạng tệp.
Scribblemacher

3
Vấn đề duy nhất với giải pháp này là khi các trình duyệt hỗ trợ SVG chứ không phải srcset. Chẳng hạn như IE11, mặc định trở lại PNG mặc dù nó hỗ trợ SVG
Hego555

16

Nếu bạn cần các SVG của mình có thể được tạo kiểu hoàn toàn bằng CSS, chúng phải nằm trong DOM. Điều này có thể đạt được thông qua việc tiêm SVG, sử dụng Javascript để thay thế một phần tử HTML (thường là một <img>phần tử) bằng nội dung của tệp SVG sau khi trang được tải.

Dưới đây là một ví dụ tối thiểu sử dụng SVGInject :

<html>
<head>
  <script src="svg-inject.min.js"></script>
</head>
<body>
  <img src="image.svg" onload="SVGInject(this)" />
</body>
</html>

Sau khi hình ảnh được tải, onload="SVGInject(this)sẽ kích hoạt tiêm và <img>phần tử sẽ được thay thế bằng nội dung của tệp được cung cấp trong srcthuộc tính. Điều này hoạt động với tất cả các trình duyệt hỗ trợ SVG.

Tuyên bố miễn trừ trách nhiệm: Tôi là đồng tác giả của SVGInject


15

Cá nhân tôi sẽ sử dụng một <svg>thẻ bởi vì nếu bạn có toàn quyền kiểm soát nó . Nếu bạn sử dụng nó, <img>bạn sẽ không kiểm soát các phần bên trong của SVG bằng CSS, v.v.

một điều nữa là hỗ trợ trình duyệt .

Chỉ cần mở svgtệp của bạn và dán thẳng vào mẫu.

<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3400 2700" preserveAspectRatio="xMidYMid meet" (click)="goHome();">
  <g id="layer101">
    <path d="M1410 2283 c-162 -225 -328 -455 -370 -513 -422 -579 -473 -654 -486 -715 -7 -33 -50 -247 -94 -475 -44 -228 -88 -448 -96 -488 -9 -40 -14 -75 -11 -78 2 -3 87 85 188 196 165 180 189 202 231 215 25 7 129 34 230 60 100 26 184 48 185 49 4 4 43 197 43 212 0 10 -7 13 -22 9 -13 -3 -106 -25 -208 -49 -102 -25 -201 -47 -221 -51 l-37 -7 8 42 c4 23 12 45 16 49 5 4 114 32 243 62 129 30 240 59 246 66 10 10 30 132 22 139 -1 2 -110 -24 -241 -57 -131 -33 -240 -58 -242 -56 -6 6 13 98 22 107 5 4 135 40 289 80 239 61 284 75 307 98 14 15 83 90 153 167 70 77 132 140 139 140 7 0 70 -63 141 -140 70 -77 137 -150 150 -163 17 -19 81 -39 310 -97 159 -41 292 -78 296 -82 8 -9 29 -106 24 -111 -1 -2 -112 24 -245 58 -134 33 -245 58 -248 56 -6 -7 16 -128 25 -136 5 -4 112 -30 238 -59 127 -29 237 -54 246 -57 11 -3 20 -23 27 -57 6 -28 9 -53 8 -54 -1 -1 -38 7 -81 17 -274 66 -379 90 -395 90 -16 0 -16 -6 3 -102 11 -57 21 -104 22 -106 1 -1 96 -27 211 -57 115 -31 220 -60 234 -66 14 -6 104 -101 200 -211 95 -111 175 -197 177 -192 1 5 -40 249 -91 542 l-94 532 -145 203 c-220 309 -446 627 -732 1030 -143 201 -265 366 -271 367 -6 0 -143 -183 -304 -407z m10 -819 l-91 -161 -209 -52 c-115 -29 -214 -51 -219 -49 -6 1 32 55 84 118 l95 115 213 101 c116 55 213 98 215 94 1 -3 -38 -78 -88 -166z m691 77 l214 -99 102 -123 c56 -68 100 -125 99 -127 -4 -3 -435 106 -447 114 -4 2 -37 59 -74 126 -38 68 -79 142 -93 166 -13 23 -22 42 -20 42 2 0 101 -44 219 -99z"/>
    <path d="M1126 2474 c-198 -79 -361 -146 -363 -147 -2 -3 -70 -410 -133 -805 -12 -73 -20 -137 -18 -143 2 -6 26 23 54 63 27 40 224 320 437 622 213 302 386 550 385 551 -2 2 -165 -62 -362 -141z"/>
    <path d="M1982 2549 c25 -35 159 -230 298 -434 139 -203 283 -413 319 -465 37 -52 93 -134 125 -182 59 -87 83 -109 73 -65 -5 20 -50 263 -138 747 -17 91 -36 170 -42 176 -9 8 -571 246 -661 280 -14 6 -7 -10 26 -57z"/>
    <path d="M1679 1291 c-8 -11 -71 -80 -141 -153 l-127 -134 -95 -439 c-52 -242 -92 -442 -90 -445 6 -5 38 28 218 223 l99 107 154 0 c85 0 163 -4 173 -10 10 -5 78 -79 151 -162 73 -84 136 -157 140 -162 18 -21 18 4 -2 85 -11 46 -58 248 -105 448 l-84 364 -87 96 c-108 121 -183 201 -187 201 -2 0 -10 -9 -17 -19z m96 -488 c33 -102 59 -189 57 -192 -2 -6 -244 -2 -251 4 -5 6 120 375 127 375 4 0 34 -84 67 -187z"/>
    </g>
  </svg>

sau đó trong css của bạn, bạn có thể chỉ cần:

svg {
  fill: red;
}

Một số tài nguyên: mẹo SVG


15

Nếu bạn sử dụng thẻ <img> , thì các trình duyệt dựa trên webkit sẽ không hiển thị hình ảnh bitmap nhúng .

Đối với bất kỳ loại sử dụng SVG nâng cao nào, bao gồm các ưu đãi nội tuyến SVG cho đến nay là tính linh hoạt nhất.

Internet Explorer và Edge sẽ thay đổi kích thước SVG một cách chính xác , nhưng bạn phải chỉ định cả chiều cao và chiều rộng.

Bạn có thể thêm onclick, onmouseover, v.v. bên trong svg, vào bất kỳ hình dạng nào trong SVG: onmouseover = "top.myfeft (evt);"

Bạn cũng có thể sử dụng phông chữ web trong SVG bằng cách đưa chúng vào biểu định kiểu thông thường của bạn.

Lưu ý: nếu bạn đang xuất SVG từ Illustrator, tên phông chữ web sẽ bị sai. Bạn có thể sửa lỗi này trong CSS của mình và tránh làm hỏng trong SVG. Ví dụ: Illustrator cung cấp tên sai cho Arial và bạn có thể sửa nó như thế này:

@font-face {    
    font-family: 'ArialMT';    
    src:    
        local('Arial'),    
        local('Arial MT'),    
        local('Arial Regular');    
    font-weight: normal;    
    font-style: normal;    
}

Tất cả điều này hoạt động trên bất kỳ trình duyệt được phát hành kể từ năm 2013 .

Ví dụ, xem ozake.com . Toàn bộ trang web được làm bằng SVG ngoại trừ mẫu liên hệ.

Cảnh báo: Phông chữ web được thay đổi kích thước không chính xác trong Safari - và nếu bạn có nhiều chuyển đổi từ văn bản đơn giản sang in đậm hoặc in nghiêng, có thể có một lượng nhỏ không gian thừa hoặc thiếu tại các điểm chuyển tiếp. Xem câu trả lời của tôi tại câu hỏi này để biết thêm thông tin.


Cảm ơn bạn. Chỉ mất 3 giờ để nhổ tóc tôi cố gắng tìm ra lý do tại sao hình ảnh raster không hiển thị trong imgthẻ của tôi ... Bạn có biết nếu điều này được ghi lại chính thức ở bất cứ đâu không?
ryebread

@Andrew Swift, bạn nhận được kết quả hình ảnh thực sự tốt trên dev.ozake.com , nhưng có vấn đề nghiêm trọng về khả năng truy cập: công cụ tìm kiếm có thể sẽ khó lập chỉ mục trang web (Tôi không chắc chắn họ sẽ chọn liên kết ẩn trong các sự kiện SVG) ; trang web không thể điều hướng bằng bàn phím; dường như những người đọc màn hình sẽ nghẹt thở vì nó ...
interDist

11

Hai xu của tôi: tính đến năm 2019, 93% trình duyệt đang sử dụng (và 100% hai phiên bản cuối cùng của mỗi một trong số chúng) có thể xử lý SVG theo <img>các yếu tố:

nhập mô tả hình ảnh ở đây

Nguồn: Tôi có thể sử dụng

Vì vậy, chúng tôi có thể nói rằng không có lý do để sử dụng <object>nữa.

Tuy nhiên, nó vẫn có ưu điểm :

  • Khi kiểm tra (ví dụ với Chrome Dev Tools), bạn sẽ thấy toàn bộ đánh dấu SVG trong trường hợp bạn muốn giả mạo một chút với nó và xem các thay đổi trực tiếp.

  • Nó cung cấp một triển khai dự phòng rất mạnh mẽ trong trường hợp trình duyệt của bạn không hỗ trợ các SVG (chờ, nhưng mỗi một trong số chúng đều có!) Cũng hoạt động nếu không tìm thấy SVG. Đây là một tính năng chính của thông số XHTML2, giống như betamax hoặc HD-DVD

Nhưng cũng có nhược điểm :


3

Tìm thấy một giải pháp với CSS thuần túy và không cần tải xuống hình ảnh kép. Nó không đẹp như tôi muốn, nhưng nó hoạt động.

<!DOCTYPE html>
<html>
  <head>
    <title>HTML5 SVG demo</title>
    <style type="text/css">
     .nicolas_cage {
         background: url('nicolas_cage.jpg');
         width: 20px;
         height: 15px;
     }
     .fallback {
     }
    </style>
  </head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
    <style>
    <![CDATA[ 
        .fallback { background: none; background-image: none; display: none; }
    ]]>
    </style>
</svg>

<!-- inline svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40">
  <switch>
     <circle cx="20" cy="20" r="18" stroke="grey" stroke-width="2" fill="#99FF66" />
     <foreignObject>
         <div class="nicolas_cage fallback"></div>
     </foreignObject>
  </switch>
</svg>
<hr/>
<!-- external svg -->
    <object type="image/svg+xml" data="circle_orange.svg">
        <div class="nicolas_cage fallback"></div>
    </object>
</body>
</html>

Ý tưởng là chèn SVG đặc biệt với kiểu dự phòng.

Thêm chi tiết và quá trình thử nghiệm bạn có thể tìm thấy trong blog của tôi .


0

jQuery này chức năng chụp tất cả các lỗi trong hình ảnh svg và thay thế phần mở rộng tập tin với phần mở rộng thay thế

Vui lòng mở giao diện điều khiển để xem lỗi tải hình ảnh svg

(function($){
  $('img').on('error', function(){
    var image = $(this).attr('src');
    if ( /(\.svg)$/i.test( image )) {
      $(this).attr('src', image.replace('.svg', '.png'));
    }
  })  
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<img src="https://jsfiddle.net/img/logo.svg">


-1

Tôi khuyên bạn nên sử dụng kết hợp

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>

bạn có thể giải thích lý do tại sao bạn sẽ sử dụng các cài đặt này và tại sao nó khác với bất kỳ câu trả lời nào khác không?
kaugeour

-1

Bạn có thể chèn một SVG gián tiếp bằng cách sử dụng <img>thẻ HTML và điều này có thể có trên StackOverflow theo những gì được mô tả dưới đây:

Tôi có tệp SVG sau trên PC

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="350" height="350" viewBox="0 0 350 350">

  <title>SVG 3 Circles Intersection </title>

    <circle cx="110" cy="110" r="100"
            stroke="red"
            stroke-width="3"
            fill="none"
            />
    <text x="110" y="110" 
          text-anchor="middle"
          stroke="red"
          stroke-width="1px"
          > Label
    </text>
    <circle cx="240" cy="110" r="100" 
            stroke="blue" 
            stroke-width="3"
            fill="none"
            />
    <text x="240" y="110" 
          text-anchor="middle" 
          stroke="blue" 
          stroke-width="1px"
          > Ticket
    </text>
    <circle cx="170" cy="240" r="100" 
            stroke="green" 
            stroke-width="3" 
            fill="none"
            />
    <text x="170" y="240" 
          text-anchor="middle" 
          stroke="green" 
          stroke-width="1px"
          > Vecto
    </text>
</svg>

Tôi đã tải hình ảnh này lên https://svgur.com

Sau khi tải lên bị chấm dứt, tôi đã nhận được URL sau:

https://svgshare.com/i/H7d.svg

Tôi có rồi CÁCH THỦ CÔNG (không sử dụng biểu tượng IMAGE) thêm vào sau thẻ html

<img src="https://svgshare.com/i/Kyp.svg"/>

và kết quả là ngay bên dưới

Đối với người dùng với một số nghi ngờ, chúng ta có thể thấy những gì tôi đã làm trong chỉnh sửa câu trả lời sau đây trên StackOverflow chèn hình ảnh SVG

LƯU Ý-1: tệp SVG phải chứa <?xml?>phần tử. Lúc đầu, tôi chỉ đơn giản là tạo một tệp SVG bắt đầu trực tiếp bằng <svg>thẻ và không có gì hoạt động!

GHI NHỚ-2: khi bắt đầu, tôi đã cố gắng chèn một hình ảnh bằng IMAGEbiểu tượng của Edit Toolbar. Tôi dán URL của tệp SVG nhưng StackOverflow không chấp nhận phương pháp này. Các <img>thẻ phải được bổ sung bằng tay.

Tôi hy vọng rằng câu trả lời này có thể giúp những người dùng khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.