여기처럼 SVG 이미지를 inline 형태로 삽입하면 HTML 코드가 복잡해질 수 있다.
당연히 <embed>, <img> 태그처럼 삽입하여 간결하게 할 수 있지만, 반응형 css 또는 script를 적용하려고 하면 문제가 생긴다.
SVG 이미지가 DOM 형태로 삽입되다 보니 HTML과 SVG 파일 각각에 존재하는 엘리먼트가 서로를 참조하기 어렵다는 것.
비록 꼼수이긴 하나 이 문제를 해소할 수 있는 방법을 포스팅한다(결론은 아래 완성 부분).
SVG 파일 내부에서 css와 jquery 사용하기
HTML에 SVG 파일 삽입 방식
object 방식 또는 embed 방식 중에 사용한다.
<div class="svg_wrap">
<object type="image/svg+xml" data="images/system.svg" id="svg_system"></object>
<!-- 또는 -->
<embed type="image/svg+xml" src="images/system.svg" id="svg_system">
</div>
추가로 아래처럼 jquery로도 가능하다.
$(".svg_wrap").load("images/system.svg");
SVG 파일에서 jquery 사용
SVG 파일에서는 .js 파일 참조 시 src 형식이 아니라 href 형식을 사용해야 한다.
xlink:href도 deprecated 상태이므로 href 만 쓴다(여기 참고).
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script href="../js/jquery-3.6.0.min.js"></script>
<!-- 생략 -->
</svg>
window.frameElement를 사용하여 SVG 파일을 감싼 부모 엘리먼트에 접근하고 다룰 수 있다.
var wrap = window.frameElement.parentNode.parentNode;
console.log( wrap );
console.log( $(wrap).hasClass("in-view") );
하지만 정작 SVG 파일 내에 존재하는 엘리먼트에는 접근할 수 없다(undefined).
- style : 부모 요소를 지정할 수 없음(SVG 파일 내 요소는 가능)
- script : 부모 요소를 지정할 수 있음(SVG 파일 내 요소는 불가능)
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script href="../js/jquery-3.6.0.min.js"></script>
<style>
.svg_wrap #moon { fill: #ff0000; }
#globe { fill: #c0c0c0; }
</style>
<script>
console.log( $("#moon") );
console.log( $("#moon").attr("cy") );
</script>
<circle id="moon" cx="15" cy="285" r="15"/>
<ellipse id="globe" cx="150" cy="150" rx="145" ry="145" fill="rgba(0,0,0,0)" stroke="rgb(0,0,0)" stroke-width="10"/>
</svg>
HTML 파일에서 SVG 파일 내의 엘리먼트 다루기(완성)
결국 inline 방식이 아니라면 SVG 파일 내부에서도, SVG 파일을 삽입한 HTML 파일에서도 css와 js 사용에 제한이 발생하기 때문에 약간의 꼼수를 사용해야 한다.
<div class="svg_wrap in-view">
<img id="svg_system" xmlns="http://www.w3.org/2000/svg" class="svg" src="images/system.svg"/>
</div>
<script>
$(document).ready(function($) {
//Redo XML
jQuery("img.svg").each(function() {
var $img = jQuery(this);
var imgID = $img.attr("id");
var imgClass = $img.attr("class");
var imgURL = $img.attr("src");
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find("svg");
// Add replaced image"s ID to the new SVG
if (typeof imgID !== "undefined") {
$svg = $svg.attr("id", imgID);
}
// Add replaced image"s classes to the new SVG
if (typeof imgClass !== "undefined") {
$svg = $svg.attr("class", imgClass+" replaced-svg");
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr("xmlns:a");
// Replace image with new SVG
$img.replaceWith($svg);
}, "xml");
});
});
$(window).on("mousewheel", function() {
if ( $(".svg_wrap").hasClass("in-view") ) {
$("#svg_system").children().attr("class", "in-view");
}
});
</script>
SVG 파일을 embed 또는 object 형태로 삽입하지 않고, img 태그를 사용한다.
그리고 스크립트에서 마치 SVG 파일을 inline으로 삽입한 것처럼 각종 속성을 끼워 맞춘다.
그런데 이 경우에도 한 가지 문제는 남아있는데, SVG 파일 내의 엘리먼트에 addClass, removeClass 메서드를 사용할 수 없다.
따라서 attr("class")를 사용하여 클래스를 조정해야 한다.
끝.
'코딩 > HTML & CSS' 카테고리의 다른 글
css - 반응형 페이지에 이미지를 정사각형으로 표시 (0) | 2023.06.20 |
---|---|
티스토리 코드블럭에 라인넘버 적용(highlightjs-line-numbers) (0) | 2022.08.10 |
pageable 풀페이지 구획별로 다르게 적용하기 (0) | 2022.07.15 |
css만으로 SVG 이미지 애니메이션 효과 적용하기 (0) | 2022.07.01 |
글자수 길이 제한 (0) | 2016.08.22 |