Closed sadr0b0t closed 7 years ago
Так, самый правильный способ масштабировать одну часть картинки и не масштабировать вторую - мог бы быть использовать атрибут vector-effect="non-scaling-size" (по аналогии с vector-effect="non-scaling-stroke" для немасштабируемой толщины линии).
Проблема в том, что эта фича есть в черновике спецификаций SVG 2.0: https://svgwg.org/svg2-draft/coords.html#VectorEffects https://www.w3.org/Graphics/SVG/WG/wiki/SVG2_Requirements_Commitments https://www.w3.org/2014/01/31-svg-minutes.html#item07 https://www.w3.org/Graphics/SVG/WG/wiki/Proposals/vector_effects_extension
Но вообще нигде не реализовано.
Обсуждение в багзиле Мозилы (есть патч, но не хотят добавлять, пока в остальных браузерах не изъявят желание добавить фичу тоже) https://bugzilla.mozilla.org/show_bug.cgi?id=1318208
еще обсуждение для Мозилы (есть предложения с альтернативами) https://groups.google.com/forum/#!topic/mozilla.dev.platform/T_7HTTdt-Es
Тикет для Хромиума https://bugs.chromium.org/p/chromium/issues/detail?id=691398
Инкскейп https://bugs.launchpad.net/inkscape/+bug/448286
Таблица фич SVG2 - строка 40 (нигде не рализовано) https://docs.google.com/spreadsheets/d/1kkqzcxY53h7liRYppLSSFG2sjaJ8V8TCP5rWLZK0AxA/edit#gid=0
Еще варианты запрос: scale svg while leaving one element unscaled https://www.yandex.ru/yandsearch?text=scale%20svg%20while%20leaving%20one%20elemtn%20unscaled&sourceid=mozilla-search&lr=116673&redircnt=1494318898.1
Non Scaling Objects / constrained transforms http://svg2.mbsrv.net/devinfo/devstd/non-scaling-objects-2/
=> Использовать трансформацию transform-ref (тоже не работает в браузерах, есть только в черновиках спеков) https://www.w3.org/TR/SVGTiny12/coords.html#transform-ref
Preserve descendant elements' size while scaling the parent element http://stackoverflow.com/questions/8880668/preserve-descendant-elements-size-while-scaling-the-parent-element
There is transform="ref(svg)" which is defined in SVG Tiny 1.2. To the best of my knowledge this is not implemented in any browsers except Opera (Presto).
Keeping SVG elements to a fixed size while position scales http://stackoverflow.com/questions/27991472/keeping-svg-elements-to-a-fixed-size-while-position-scales
Еще предлагают использовать elem.getCTM() в яваскрипте (в этом случае еще придется отлавливать события масштабирования).
var circle = document.getElementById('c');
var root = document.getElementById('root');
var matrix = circle.getCTM();
circle.r.baseVal.value /= matrix.a;
Еще getCTM() и другие варианты
Scale independent elements http://stackoverflow.com/questions/10694347/scale-independent-elements
How to draw non-scalable circle in SVG with Javascript http://stackoverflow.com/questions/10473328/how-to-draw-non-scalable-circle-in-svg-with-javascript
еще близко к теме
Как попасть мышкой в элемент на отмасштабированном SVG
SVG coordinates with transform matrix http://stackoverflow.com/questions/4850821/svg-coordinates-with-transform-matrix
ответ в виде интерактивного демо: http://phrogz.net/svg/drag_under_transformation.xhtml
How do you convert screen coordinates to document space in a scaled SVG? http://stackoverflow.com/questions/22183727/how-do-you-convert-screen-coordinates-to-document-space-in-a-scaled-svg
везде предлагают использовать getScreenCTM()
про режимы мастшабирования с viewBox и preserveAspectRatio в SVG https://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute
единицы измерения SVG https://www.w3.org/TR/SVG11/coords.html#Units
How to Scale SVG https://css-tricks.com/scale-svg/
там идет тема, как сделать разные области SVG с разным масштабом
предлагают использовать вложенные блоки SVG
Еще предлагают использовать elem.getCTM() в яваскрипте (в этом случае еще придется отлавливать события масштабирования).
про масштабирование (изменение размера окна) - есть событие onresize.
https://www.w3schools.com/JSREF/event_onresize.asp http://help.dottoro.com/ljorlllt.php
<body onresize="myFunction()">
Но приклеить его можно только к окну window или тегу body (на div не сработает).
В реакте сделал следующее:
render: function() {
window.onresize = function() {
console.log("resize");
}
...
}
все работает, сыпет в консоль сообщениями при любом изменении размеров окна или страницы.
Для радиуса кружочка сработало вот так:
window.onresize = function() {
console.log("resize");
var circle = document.getElementById('tool_x_y');
var matrix = circle.getCTM();
circle.r.baseVal.value = toolMM.z_radius / matrix.a;
здесь toolMM.z_radius - целевое значение радиуса (вычисленное заранее или константа).
делать так, как в примере выше (использовать значение радиуса из элемента):
circle.r.baseVal.value /= matrix.a;
нельзя, т.к. при множественных изменениях размеров окна значение радиуса в дефолтное значение сбрасываеться не будет и при множественных делениях на коэффециент улетит в ноль.
Решение с кружочком и надписями, не зависящими от масштаба. Еще осталось разобраться с крестиком внутри кружочка с рабочим инструметом (это понятно) и боковыми отступами (это, похоже, будет похитрее).
это отрабатывает только при изменении размеров окна:
render: function() {
var lab_txt_size = 12;
window.onresize = function() {
//console.log("resize");
var circle = document.getElementById('tool_x_y');
var matrix = circle.getCTM();
document.getElementById('tool_x_y').r.baseVal.value = toolMM.z_radius / matrix.a;
document.getElementById('lab_xy_0').style.fontSize = lab_txt_size / matrix.a;
document.getElementById('lab_x').style.fontSize = lab_txt_size / matrix.a;
document.getElementById('lab_y').style.fontSize = lab_txt_size / matrix.a;
document.getElementById('lab_z_0').style.fontSize = lab_txt_size / matrix.a;
document.getElementById('lab_z').style.fontSize = lab_txt_size / matrix.a;
}
...
}
при перересовке (и даже первой отрисовке) виджета средствами реакта колбэк вызван не будет и масштаб может быть покорежен.
Помогает вот такой хак (или, может, вполне справедливое решение):
componentDidMount: function() {
window.onresize();
},
componentDidUpdate: function() {
window.onresize();
}
componentDidMount вызывается после первой отрисовки виджета, componentDidUpdate - после каждой перерисовки, оба - после render (это значит, что все элементы уже отправлены в ДОМ).
React.Component, The Component Lifecycle https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle
не зависят от текущего масштаба:
Подзадача отсюда отдельным тикетом
Выбрать движок SVG для React: система координат https://github.com/1i7/babbler-robots/issues/2
При достаточно большом реальном размере рабочей области 300000x200000 (микрометры) с масштабированием рабочей области к видимым размерам на экране было две проблемы:
С полем 300x200 в обоих случаях всё ок.
Первая проблема решилась добавлением стиля vector-effect:"non-scaling-stroke" к линии или прямоугольнику https://github.com/1i7/babbler-robots/issues/2#issuecomment-283461267
Со второй проблемой нужно разобраться в этом тикете.
Видятся решения:
для затравки: How to Scale SVG https://css-tricks.com/scale-svg/
там идет тема, как сделать разные области SVG с разным масштабом