Skip to content

Instantly share code, notes, and snippets.

@pjchender
Last active March 17, 2017 08:45
Show Gist options
  • Save pjchender/dcaf9b0e6829b5a8fd3b76b135082c30 to your computer and use it in GitHub Desktop.
Save pjchender/dcaf9b0e6829b5a8fd3b76b135082c30 to your computer and use it in GitHub Desktop.
function to Zoom and Drag SVG
function reportMouseCoordinates (evt) {
const offsetXY = document.getElementById('offsetXY')
const clientXY = document.getElementById('clientXY')
const svgXY = document.getElementById('svgXY')
const svgElement = document.getElementById('svgElement')
offsetXY.textContent = `Offset:(${evt.offsetX}, ${evt.offsetY})`
clientXY.textContent = `Client(screen): (${evt.clientX}, ${evt.clientY})`
const screenPoint = svgElement.createSVGPoint()
screenPoint.x = evt.clientX
screenPoint.y = evt.clientY
let CTM = svgElement.getScreenCTM()
let svgPoint = screenPoint.matrixTransform(CTM.inverse())
svgXY.textContent = `SVGPoint(viewbox): (${svgPoint.x.toFixed(0)}, ${svgPoint.y.toFixed(0)})`
}
let select
function startDrag () {
select = true
}
function drag (evt) {
if (select) {
const svgElement = document.getElementById('svgElement')
const screenPoint = svgElement.createSVGPoint()
let viewBox
let CTM
console.group()
console.log('一開始的viewBox', svgElement.getAttribute('viewBox'))
// 取得滑鼠當前點擊的座標
let clientXY = {
x: evt.clientX,
y: evt.clientY
}
console.log('clientXY', clientXY)
// 轉換為滑鼠當前點擊 SVG 座標
screenPoint.x = clientXY.x
screenPoint.y = clientXY.y
console.log('screePoint', screenPoint)
CTM = svgElement.getScreenCTM()
let svgPoint = screenPoint.matrixTransform(CTM.inverse())
console.log('svgPoint', svgPoint)
// 取得滑鼠後來的座標
let clientXYAfterDrag = {
x: evt.clientX + evt.movementX,
y: evt.clientY + evt.movementY
}
console.log('clientXYAfterDrag', clientXYAfterDrag)
// 轉換為滑鼠後來的 SVG 座標
screenPoint.x = clientXYAfterDrag.x
screenPoint.y = clientXYAfterDrag.y
let svgPointAfterDrag = screenPoint.matrixTransform(CTM.inverse())
console.log('svgPointAfterDrag', svgPointAfterDrag)
// 計算位移量
viewBox = svgElement.getAttribute('viewBox').split(' ').map(n => parseFloat(n))
let viewBoxAfterTranslate = {
x: viewBox[0] + (svgPoint.x - svgPointAfterDrag.x),
y: viewBox[1] + (svgPoint.y - svgPointAfterDrag.y)
}
svgElement.setAttribute('viewBox', `${viewBoxAfterTranslate.x} ${viewBoxAfterTranslate.y} ${viewBox[2]} ${viewBox[3]}`)
console.log('最後的 viewBox', svgElement.getAttribute('viewBox'))
console.groupEnd()
}
}
function endDrag () {
select = false
}
function zoom (evt) {
console.groupCollapsed()
const svgElement = document.getElementById('svgElement')
let viewBox
let r = 0.95 // ratio to scale
let CTM
if (evt.deltaY > 0) {
r = 0.9
} else if (evt.deltaY < 0) {
r = 1.1
} else {
r = 1
}
console.log('r', r)
// 取得滑鼠滾動螢幕座標
let clientXY = {
x: evt.clientX,
y: evt.clientY
}
// 轉換為滑鼠滾動 SVG 座標
const screenPoint = svgElement.createSVGPoint()
screenPoint.x = clientXY.x // evt.clientX
screenPoint.y = clientXY.y // evt.clientY
console.log('screePoint', screenPoint)
CTM = svgElement.getScreenCTM()
let svgPoint = screenPoint.matrixTransform(CTM.inverse())
console.log('svgPoint', svgPoint)
// 將滑鼠滾動 SVG 座標移動中心點,並放大
viewBox = svgElement.getAttribute('viewBox').split(' ').map(n => parseFloat(n))
console.log('原始viweBox', viewBox)
svgElement.setAttribute('viewBox', `${viewBox[0] + svgPoint.x} ${viewBox[1] + svgPoint.y} ${viewBox[2] * r} ${viewBox[3] * r}`)
// 將 SVG 座標從中心點移回原本的 ClientXY 的 SVG 位移
CTM = svgElement.getScreenCTM()
let svgPointAfterWheel = screenPoint.matrixTransform(CTM.inverse())
console.log('後來的 svgPointAfterWheel', svgPointAfterWheel)
viewBox = svgElement.getAttribute('viewBox').split(' ').map(n => parseFloat(n))
console.log('置中與放大的 viweBox', viewBox)
let viewBoxAfterTranslate = {
x: viewBox[0] + (svgPoint.x - svgPointAfterWheel.x), // viewBox[0] + (svgPointAfterWheel.x - svgPoint.x)
y: viewBox[1] + (svgPoint.y - svgPointAfterWheel.y) // viewBox[1] + (svgPointAfterWheel.y - svgPoint.y)
}
svgElement.setAttribute('viewBox', `${viewBoxAfterTranslate.x} ${viewBoxAfterTranslate.y} ${viewBox[2]} ${viewBox[3]}`)
console.log('最後的 viewBox', svgElement.getAttribute('viewBox'))
console.groupEnd()
}
function init () {
const svgElement = document.getElementById('svgElement')
svgElement.addEventListener('mousemove', reportMouseCoordinates, false)
svgElement.addEventListener('wheel', zoom, false)
svgElement.addEventListener('mousedown', startDrag, false)
svgElement.addEventListener('mousemove', drag, false)
svgElement.addEventListener('mouseup', endDrag, false)
}
window.addEventListener('load', init, false)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment