'Create a SVG where everything scales except text
To illustrate the effect I'm after, say we scale the image vertically:
Before:

After:

Note the text doesn't distort. I'm looking for an easier alternative to drawing and positioning the elements manually each time the scale changes, particularly where the text stays the same dimensions, and I thought svg could pull this off...
Solution 1:[1]
Long time since this question has been made. I think that is not possible without JavaScript. If you do not have problems with the use of JavaScript, use this plugin. The plugin gets all svg elements with an specific class and creates on each element a transformation matrix:
This plugin requires that the svg has the viewBox option. It is a start point, you could adapt it to your needs ;)
(function($){
var defaults = { class: "no-scale" };
var methods = {
//---Init method
init: function(){
//---Conform the settings
var settings = $.extend({}, defaults);
return this.each(function(index){
//---Get the SVG
var svg = $(this);
//---Get the viewBox (svgRect)
var viewBox = (svg[0].viewBox == undefined) ? false : svg[0].viewBox.animVal;
//---Store the data
svg.data({"viewBox": viewBox, settings: settings});
//---Call to private function of resize elements
private.updateSizes(svg);
});
},
refresh: function(){
return this.each(function(index){
//---Get the SVG
var svg = $(this);
//---Call to private function of resize elements
private.updateSizes(svg);
});
}
};
var private = {
updateSizes: function(svg){
//---Get the viewBox (svgRect)
var viewBox = svg.data("viewBox");
if(!viewBox) return;
//---Get the settings
var settings = svg.data("settings");
//---Global scale
var scalew = Math.round((svg.width() / viewBox.width) * 100) / 100;
var scaleh = Math.round((svg.height() / viewBox.height) * 100) / 100;
//---Get the resized elements
var noScaleElements = svg.find("." + settings.class);
noScaleElements.each(function(){
var el = $(this);
//---Set variables
var sw = el.width();
var sh = el.height();
var sx = Math.round((1 / scalew) * 100) / 100;
var sy = Math.round((1 / scaleh) * 100) / 100;
var tx = Number( el.attr("x") ) * (1 - sx) + ((sw - sw * sx) / 2) * sx;
var ty = Number( el.attr("y") ) * (1 - sy) + ((sh * sy - sh) / 2) * sy;
var matrix = "matrix(" + sx + ",0,0," + sy + "," + tx + "," + ty + ")";
$(this).attr("transform", matrix);
});
}
};
$.fn.noScaleSVGElements = function(method){
// Method calling logic
if (methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.noScaleSVGElements' );
}
}
})(jQuery);
To use the plugin:
//---Code
$("#svg-element").noScaleSVGElements();
//---Call this method every time that the sizes need to be recalculated
$("#svg-element").noScaleSVGElements("refresh");
Here you have a snippet, change the window size and check the result:
//---Plugin jQuery
(function($){
var defaults = { class: "no-scale" };
var methods = {
//---Init method
init: function(){
//---Conform the settings
var settings = $.extend({}, defaults);
return this.each(function(index){
//---Get the SVG
var svg = $(this);
//---Get the viewBox (svgRect)
var viewBox = (svg[0].viewBox == undefined) ? false : svg[0].viewBox.animVal;
//---Store the data
svg.data({"viewBox": viewBox, settings: settings});
//---Call to private function of resize elements
private.updateSizes(svg);
});
},
refresh: function(){
return this.each(function(index){
//---Get the SVG
var svg = $(this);
//---Call to private function of resize elements
private.updateSizes(svg);
});
}
};
var private = {
updateSizes: function(svg){
//---Get the viewBox (svgRect)
var viewBox = svg.data("viewBox");
if(!viewBox) return;
//---Get the settings
var settings = svg.data("settings");
//---Global scale
var scalew = Math.round((svg.width() / viewBox.width) * 100) / 100;
var scaleh = Math.round((svg.height() / viewBox.height) * 100) / 100;
//---Get the resized elements
var noScaleElements = svg.find("." + settings.class);
noScaleElements.each(function(){
var el = $(this);
//---Set variables
var sw = el.width();
var sh = el.height();
var sx = Math.round((1 / scalew) * 100) / 100;
var sy = Math.round((1 / scaleh) * 100) / 100;
var tx = Number( el.attr("x") ) * (1 - sx) + ((sw - sw * sx) / 2) * sx;
var ty = Number( el.attr("y") ) * (1 - sy) + ((sh * sy - sh) / 2) * sy;
var matrix = "matrix(" + sx + ",0,0," + sy + "," + tx + "," + ty + ")";
el.attr("transform", matrix);
});
}
};
$.fn.noScaleSVGElements = function(method){
// Method calling logic
if (methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.noScaleSVGElements' );
}
}
})(jQuery);
//---Code
$("#container svg").noScaleSVGElements();
$(window).resize(function(){
$("#container svg").noScaleSVGElements("refresh");
});
html, body{
height: 100%;
}
body{
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<svg x="0px" y="0px" width="100%" height="100%" viewBox="0 0 150 150" preserveAspectRatio="none">
<polyline fill="#FFFFFF" stroke="#231F20" stroke-width="1.2241" stroke-miterlimit="10" points="29.333,11.223 136.223,11.223
136.223,138.777 29.333,138.777 " vector-effect="non-scaling-stroke"/>
<line fill="none" stroke="#231F20" stroke-width="1.2241" stroke-miterlimit="10" x1="135.447" y1="75" x2="30.109" y2="75" vector-effect="non-scaling-stroke"/>
<text class="no-scale" x="5.1113" y="14.7451" font-family="'MyriadPro-Regular'" font-size="12">100</text>
<text class="no-scale" x="5.1113" y="78.5215" font-family="'MyriadPro-Regular'" font-size="12">50</text>
<text class="no-scale" x="5.1113" y="142.2988" font-family="'MyriadPro-Regular'" font-size="12">0</text>
</svg>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
