SVG 取得滑鼠座標資訊
Describe how to get point in the viewport coordinate system and point in the SVG coordinate system. In addition, How to transform between them.
by Po-Jung Chen
HTML
<svg id="svg" width="600" height="300" viewBox="0 0 600 300">
<rect x="0" y="0" fill="none" stroke="#EB7B2D" stroke-width="2" width="600" height="300" />
<circle cx="300" cy="150" r="5" fill="#EB7B2D" />
</svg>
<!-- 取得滑鼠座標資訊 -->
<div id="info">
<p id="offset">offset</p>
<p id="client">client</p>
<p id="showSvg">svg</p>
</div>
<!-- 設定 viewBox 用 -->
<div class="manipulate">
<div id="currentViewBox"></div>
<input type="number" name="viewBox-x-min" id="viewBox-x-min" placeholder="x-min">
<input type="number" name="viewBox-y-min" id="viewBox-y-min" placeholder="y-min">
<input type="number" name="viewBox-width" id="viewBox-width" placeholder="width">
<input type="number" name="viewBox-height" id="viewBox-height" placeholder="height">
<button id="setViewBoxBtn">設定</button>
</div>
CSS
svg {
border: 1px solid #333;
}
#info {
box-sizing: border-box;
border: 1px solid #DEDEDE;
padding: 10px;
width: 600px;
}
#info p {
margin: 0;
padding: 1px;
}
/* Other CSS Style reference from Pure CSS */
.manipulate input {
width: 100px;
padding: .5em .6em;
display: inline-block;
border: 1px solid #ccc;
box-shadow: inset 0 1px 3px #ddd;
border-radius: 4px;
vertical-align: middle;
box-sizing: border-box;
}
button {
font-family: "微軟正黑體";
font-size: 100%;
padding: .5em .6em;
color: #444;
color: rgba(0, 0, 0, .8);
border: 1px solid #999;
border: transparent;
background-color: #E6E6E6;
text-decoration: none;
border-radius: 2px;
}
button:hover{
background-image: linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));
}
JavaScript
// 取得當前的 viewBox 資訊
function showViewBox() {
const currentViewBox = document.getElementById('currentViewBox')
let viewBox = svg.getAttribute('viewBox')
currentViewBox.textContent = `現在的 viewBox 為:(${viewBox})`
}
// 讓使用者可以設定 viewBox
function setViewBox() {
// 取得使用者輸入的 viewBox 值
const xMin = document.querySelector('[name="viewBox-x-min"]')
const yMin = document.querySelector('[name="viewBox-y-min"]')
const width = document.querySelector('[name="viewBox-width"]')
const height = document.querySelector('[name="viewBox-height"]')
let viewBox = `${xMin.value} ${yMin.value} ${width.value} ${height.value}`
// 設定 SVG viewBox 屬性值
svg.setAttribute('viewBox', viewBox)
// 顯示最新的 viewBox 資訊
showViewBox()
}
/*
* 開始:取得游標座標資訊
*/
function reportCurrentPoint(e) {
// 選取 HTML 各元素
const info = document.getElementById('info')
const offset = document.getElementById('offset')
const client = document.getElementById('client')
const showSvg = document.getElementById('showSvg')
// 取得 viewport 座標系統中的 offset 和 client 座標值,並顯示於視窗上
offset.textContent = `offset (${e.offsetX}, ${e.offsetY})`
client.textContent = `client (${e.clientX}, ${e.clientY})`
// 建立 SVG 座標點(0, 0)
const clientPoint = svg.createSVGPoint()
// 取得 CTM
const CTM = svg.getScreenCTM()
// 將 SVG 座標點的 x, y 設成 client(x, y)
clientPoint.x = e.clientX
clientPoint.y = e.clientY
// 將 client 的座標點轉成 SVG 座標點
SVGPoint = clientPoint.matrixTransform(CTM.inverse())
// 將資訊顯示於視窗上
showSvg.textContent = `svg (${SVGPoint.x.toFixed(0)}, ${SVGPoint.y.toFixed(0)})`
} // 結束:取得游標座標資訊
const svg = document.getElementById('svg')
const setViewBoxBtn = document.getElementById('setViewBoxBtn')
svg.addEventListener('mousemove', reportCurrentPoint)
setViewBoxBtn.addEventListener('click', setViewBox)
showViewBox()