Use CSS transformations instead of manipulating the viewBox

This commit is contained in:
2024-04-20 19:34:06 -07:00
parent 263201d869
commit 2d3fc1cd22
11 changed files with 273 additions and 195 deletions

View File

@@ -0,0 +1,40 @@
body {
text-align: center;
max-width: 100vw;
}
.container {
padding: 0;
max-width: 586.033px;
max-height: 586.033px;
margin: 0 auto;
overflow: hidden;
border: 1px solid steelblue;
background-color: gray;
}
img, object {
touch-action: none;
}
img {
max-width: 100%;
border: 1px solid silver;
transform: scale(0.9);
}
.container object, .container.switch img {
display: block;
}
.container img, .container.switch object {
display: none;
}
button .button-text.raster, button.switch .button-text.svg {
display: none;
}
button.switch .button-text.raster {
display: inline;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="-200 -150 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
svg {
overflow: hidden;
border: 1px solid silver;
transform: scale(0.9);
}
circle, rect {
fill-opacity: 0.9;
filter: drop-shadow(5px 5px 2px rgba(0, 0, 0, .5));
}
</style>
<script type="text/javascript">//<![CDATA[
const svgns = 'http://www.w3.org/2000/svg',
svg = document.querySelector('svg'),
{ x: vbX, y: vbY, width: vbWidth, height: vbHeight } = svg.viewBox.baseVal,
shapeCount = 100,
circleRadius = { min: 5, max: 45 },
rectSideLength = { min: 5, max: 95 },
colorValRange = { min: 0, max: 255 },
shadeFactorRange = { min: 0.3, max: 0.7 };
// source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
const minCeiled = Math.ceil(min),
maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled);
}
// source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_number_between_two_values
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
function getRandomColorValue() {
return getRandomIntInclusive(colorValRange.min, colorValRange.max);
}
function getRandomShadeFactor() {
return getRandomArbitrary(shadeFactorRange.min, shadeFactorRange.max);
}
function getRandomOrigin() {
return {
x: getRandomIntInclusive(vbX, vbX + vbWidth),
y: getRandomIntInclusive(vbY, vbY + vbHeight)
}
}
function getRandomFillAndStrokeVals() {
const fill = ['r', 'g', 'b'].map(() => getRandomColorValue()),
stroke = fill.map(v => Math.floor(v * getRandomShadeFactor()));
return {
fill: fill,
stroke: stroke
};
}
function getRandomCircle(fill, stroke) {
const el = document.createElementNS(svgns, 'circle'),
r = getRandomIntInclusive(circleRadius.max, circleRadius.min),
origin = getRandomOrigin();
el.setAttributeNS(null, 'cx', origin.x);
el.setAttributeNS(null, 'cy', origin.y);
el.setAttributeNS(null, 'r', r);
el.setAttributeNS(null, 'fill', fill);
el.setAttributeNS(null, 'stroke', stroke);
return el;
}
function getRandomRect(fill, stroke) {
const el = document.createElementNS(svgns, 'rect'),
[width, height] = ['w', 'h'].map(() =>
getRandomIntInclusive(rectSideLength.max, rectSideLength.min)
),
origin = getRandomOrigin();
el.setAttributeNS(null, 'x', origin.x);
el.setAttributeNS(null, 'y', origin.y);
el.setAttributeNS(null, 'width', width);
el.setAttributeNS(null, 'height', height);
el.setAttributeNS(null, 'fill', fill);
el.setAttributeNS(null, 'stroke', stroke);
return el;
}
function getRandomShape({ fill: fillVals, stroke: strokeVals }) {
const shape = [getRandomCircle, getRandomRect][Math.round(Math.random())],
[fill, stroke] = [fillVals, strokeVals].map(v => `rgb(${v.join(', ')})`);
return shape(fill, stroke);
}
[...Array(shapeCount)]
.map(() => getRandomFillAndStrokeVals())
.forEach(fillAndStrokeVal => svg.appendChild(getRandomShape(fillAndStrokeVal)));
//]]></script>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,82 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
svg {
overflow: hidden;
}
circle, rect {
fill-opacity: 0.9;
}
</style>
<script type="text/javascript">//<![CDATA[
const svgns = 'http://www.w3.org/2000/svg',
svg = document.querySelector('svg'),
{ width: vbWidth, height: vbHeight } = svg.viewBox.baseVal,
shapeCount = 100,
maxColorValue = 256,
circleRadius = { max: 45, min: 5 },
rectSideLength = { max: 95, min: 5 };
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function getRandomPositiveInt(max) {
return getRandomInt(max) + 1;
}
function getRandomFillAndStrokeVals() {
const shadeFactor = Math.random(),
fill = ['r', 'g', 'b'].map(() => getRandomInt(maxColorValue)),
stroke = fill.map(v => Math.floor(v * shadeFactor));
return {
fill: fill,
stroke: stroke
};
}
function getRandomCircle(fill, stroke) {
const el = document.createElementNS(svgns, 'circle'),
r = getRandomPositiveInt(circleRadius.max) + circleRadius.min;
el.setAttributeNS(null, 'cx', getRandomInt(vbWidth));
el.setAttributeNS(null, 'cy', getRandomInt(vbHeight));
el.setAttributeNS(null, 'r', r);
el.setAttributeNS(null, 'fill', fill);
el.setAttributeNS(null, 'stroke', stroke);
return el;
}
function getRandomRect(fill, stroke) {
const el = document.createElementNS(svgns, 'rect'),
[width, height] = ['w', 'h'].map(() =>
getRandomPositiveInt(rectSideLength.max) + rectSideLength.min
);
el.setAttributeNS(null, 'x', getRandomInt(vbWidth));
el.setAttributeNS(null, 'y', getRandomInt(vbHeight));
el.setAttributeNS(null, 'width', width);
el.setAttributeNS(null, 'height', height);
el.setAttributeNS(null, 'fill', fill);
el.setAttributeNS(null, 'stroke', stroke);
return el;
}
function getRandomShape({ fill: fillVals, stroke: strokeVals }) {
const shapes = [getRandomCircle, getRandomRect],
[fill, stroke] = [fillVals, strokeVals].map(v => `rgb(${v.join(', ')})`);
return shapes[getRandomInt(shapes.length)](fill, stroke);
}
[...Array(shapeCount)]
.map(() => getRandomFillAndStrokeVals())
.forEach(fillAndStrokeVal => svg.appendChild(getRandomShape(fillAndStrokeVal)));
//]]></script>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -3,31 +3,28 @@
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>SVG Pan & Zoom Example</title>
<style>
body {
text-align: center;
max-width: 100vw;
}
object {
max-height: 400px;
max-width: 100%;
background-color: lightsteelblue;
border: 1px solid steelblue;
touch-action: none;
}
</style>
<title>JavaScript/CSS Pan & Zoom Demo</title>
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<h1>Pan & Zoom an SVG Image with JavaScript</h1>
<h1>Pan & Zoom an Element with CSS/JavaScript</h1>
<p>
Click and drag on the image to pan. Use the mouse wheel
to zoom in and out.
</p>
<object type="image/svg+xml" data="image.svg"></object>
<p>
<button>
<span class="button-text svg">Raster image</span>
<span class="button-text raster">SVG image</span>
</button>
</p>
<div class="container">
<object type="image/svg+xml" data="assets/images/image.svg"></object>
<img src="assets/images/41156165560-4438592e93-o.webp"/>
</div>
<script src="app.js"></script>
</body>
</html>