एसवीजी में ट्रांसफॉर्म मूल कैसे सेट करें


104

मुझे जावास्क्रिप्ट का उपयोग करके एसवीजी दस्तावेज़ में कुछ तत्वों का आकार बदलने और घुमाने की आवश्यकता है। समस्या यह है कि डिफ़ॉल्ट रूप से, यह हमेशा मूल के (0, 0)ऊपर - ऊपर बाईं ओर परिवर्तन को लागू करता है ।

मैं इस एंकर बिंदु को फिर से कैसे परिभाषित कर सकता हूं?

मैंने transform-originविशेषता का उपयोग करने की कोशिश की , लेकिन यह कुछ भी प्रभावित नहीं करता है।

मैंने इस तरह से इसे किया:

svg.getDocumentById('someId').setAttribute('transform-origin', '75 240');

यह मेरे द्वारा निर्दिष्ट बिंदु पर महत्वपूर्ण बिंदु सेट नहीं करता है, हालांकि मैं फ़ायरफ़ॉक्स में देख सकता हूं कि विशेषता सही रूप से सेट है। मैंने कोष्ठक के बिना center bottomऔर 50% 100%साथ की चीजों की कोशिश की । अब तक कुछ भी काम नहीं किया।

क्या कोई मदद कर सकता है?


FWIW, माना जाता है कि फ़ायरफ़ॉक्स 19 बीटा 3 के रूप में तय किया गया है, हालाँकि मुझे अभी भी फ़ायरफ़ॉक्स 22 में समस्या आ रही है। मोज़िला बगज़िला लिस्टिंग: Bugzilla.mozilla.org/show_bug.cgi?id=828286
Toph

जवाबों:


147

रोटेट का उपयोग करने के लिए transform="rotate(deg, cx, cy)", जहां डिग वह डिग्री है जिसे आप घुमाना चाहते हैं और (cx, cy) रोटेशन के केंद्र को परिभाषित करते हैं।

स्केलिंग / आकार बदलने के लिए, आपको (-xx, -cy) द्वारा अनुवाद करना होगा, फिर स्केल करना होगा और फिर वापस (cx, cy) में अनुवाद करना होगा। आप इसे मैट्रिक्स रूपांतरण के साथ कर सकते हैं :

transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"

जहां x- अक्ष में sx स्केलिंग कारक है, y- अक्ष में sy।


बहुत बहुत धन्यवाद। घुमाएँ पूरी तरह से मुझे लगता है कि काम करता है, लेकिन स्केलिंग / आकार बदलना हमेशा कुछ यादृच्छिक राशि से समाप्त होता है। मैंने मैट्रिक्स का उपयोग करने और उन्हें अलग-अलग करने का प्रयास किया जैसे "अनुवाद (सीएक्स एसएक्स, साइबर एसई) स्केल (एसएक्स, एसवाई)"। वही परिणाम।
CTheDark

6
क्या यह रूपांतरण नहीं होगा = "मैट्रिक्स (sx, 0, 0, sy, cx-sx cx, cy-sy cy)"? क्योंकि आप केवल अंतर से अनुवाद करना चाहते हैं। मुझे लगता है कि यह तर्क सही है, लेकिन यह अभी भी मुझे पद से हटा देता है ...
CTheDark

अब यह काम कर रहा है! मैं सिर्फ गलत cx और साइबर मूल्यों का उपयोग कर रहा था! आपका बहुत बहुत धन्यवाद!
CTheDark

1
@JayStevens हाँ, मैट्रिक्स रूपांतरण किसी भी प्रणाली के लिए काम करेगा, यह सिर्फ गणित है। एकमात्र अंतर संकेतन हो सकता है। जहाँ तक मैं बता सकता हूँ, CSS मैट्रिक्स ट्रांसफ़ॉर्मेशन SVGs के लिए समान नोटेशन का उपयोग करता है, इसलिए उस क्रम में समान छह नंबर काम करने चाहिए।
पीटर कॉलिंगरिज

1
बस स्पष्ट करने के लिए, cx और cy को आपके स्केलिंग बॉक्स के केंद्र से दूर होने की आवश्यकता है । इसने मुझे थोड़ा आगे बढ़ा दिया, जैसा कि मैं CSS बॉक्स मॉडल में सोच रहा था। @forresto नीचे दिए गए अपने जवाब में यह दृष्टिकोण देता है।
जेसन फ़ार्न्सवर्थ

22

यदि आप एक निश्चित मान ("केंद्र" या "50%") का उपयोग कर सकते हैं, तो आप इसके बजाय CSS का उपयोग कर सकते हैं:

-moz-transform-origin: 25px 25px;
-ms-transform-origin:  25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin:  25px 25px;
transform-origin: 25px 25px;

कुछ ब्राउज़र (जैसे फ़ायरफ़ॉक्स) सापेक्ष मूल्यों को सही ढंग से नहीं संभालेंगे।


1
वाह। अगर मैं कर सकता था +10। इससे मेरा दिन बच गया! धन्यवाद।
०३:०६ पर कलुब

यह कैसे करना है और जावास्क्रिप्ट में बस?
एंड्रयू एस

पसंद है element.setAttribute('transform-origin', '25px 25px')?
नीक

13

यदि आप मेरे जैसे हैं और पैन करना चाहते हैं और फिर ट्रांसफॉर्म-ओरिजिन के साथ जूम करना चाहते हैं, तो आपको थोड़ी और आवश्यकता होगी।

// <g id="view"></g>
var view = document.getElementById("view");

var state = {
  x: 0,
  y: 0,
  scale: 1
};

// Origin of transform, set to mouse position or pinch center
var oX = window.innerWidth/2;
var oY = window.innerHeight/2;

var changeScale = function (scale) {
  // Limit the scale here if you want
  // Zoom and pan transform-origin equivalent
  var scaleD = scale / state.scale;
  var currentX = state.x;
  var currentY = state.y;
  // The magic
  var x = scaleD * (currentX - oX) + oX;
  var y = scaleD * (currentY - oY) + oY;

  state.scale = scale;
  state.x = x;
  state.y = y;

  var transform = "matrix("+scale+",0,0,"+scale+","+x+","+y+")";
  //var transform = "translate("+x+","+y+") scale("+scale+")"; //same
  view.setAttributeNS(null, "transform", transform);
};

यहाँ यह काम कर रहा है: http://forresto.github.io/dataflow-prototyping/react/


आपका
गीथब

नमस्कार @NuclearPeon, यह बहुत बढ़िया है, लेकिन मैं इसे अपने कोड में लागू नहीं कर सकता। एसवीजी तत्व मैं इसे लागू करना चाहता हूं, पहले से ही एक चर है जिसे "मेनग्रिड" कहा जाता है। मैंने बिना किसी प्रभाव के "mainGrid" के साथ "दृश्य" के उदाहरण को बदलने की कोशिश की। मैं क्या खो रहा हूँ? धन्यवाद!
सैकफ्रेट

@ जांच करने के लिए सबसे स्पष्ट बातें @sakeferret है कि दस्तावेजों और विशेषताओं idमें मेल खाता है । कोड को देखे बिना सुनिश्चित करना कठिन है। यदि आप इसे एसओ प्रश्न के रूप में पोस्ट नहीं करना चाहते हैं, तो आप अपने विशेषता नामों का उपयोग करके सबसे सरल उदाहरण बनाने का प्रयास कर सकते हैं जब तक कि यह काम नहीं करता / जब आप समस्या पाते हैं, तो बाकी को वापस जोड़ दें।getElementByIdid="..."
NuclearPeon

12

matrixपरिवर्तन का उपयोग किए बिना स्केलिंग के लिए :

transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"

और यहाँ यह CSS में है:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)

1

ऐसा लगता है कि हम सब यहाँ एक चाल से चूक गए हैं: transform-box: fill-box

transform-box: fill-boxएसवीजी के भीतर एक तत्व का उपयोग करना एक सामान्य एचटीएमएल तत्व के रूप में व्यवहार करेगा। फिर आप transform-origin: centerसामान्य रूप से आवेदन कर सकते हैं (या कुछ और)

यह सही है, transform-box: fill-boxकिसी भी जटिल मैट्रिक्स सामान की आवश्यकता नहीं है


बहुत उपयोगी समाधान, यह बोना उच्चतर उत्कीर्ण किया जाएगा। मुझे ठीक इसी की आवश्यकता थी; धन्यवाद! रूपांतरण और संक्रमण के दौरान svg और html तत्वों में सूक्ष्म अंतर होता है। मैं घंटों के लिए एक एनीमेशन बग के साथ हैरान था, जब तक कि मुझे यह जवाब नहीं मिला ... transform-box: fill-box;आप के साथ svg तत्व को सम्मानजनक transform-originतरीके से बना सकते हैं / जैसे आप उम्मीद करेंगे!
zfogg

-1

मेरा मुद्दा भी ऐसा ही था। लेकिन मैं अपने तत्वों को स्थिति में लाने के लिए डी 3 का उपयोग कर रहा था , और चाहता था कि परिवर्तन और परिवर्तन सीएसएस द्वारा संभाला जाए। यह मेरा मूल कोड था, जिसे मुझे Chrome 65 में काम करना था:

//...
this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('circle')
  .attr('transform-origin', (d,i)=> `${valueScale(d.value) * Math.sin( sliceSize * i)} 
                                     ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)}`)
//... etc (set the cx, cy and r below) ...

यह मैं सेट करने की अनुमति cx, cyऔर transform-originएक ही डेटा का उपयोग कर जावास्क्रिप्ट में मान।

लेकिन यह फ़ायरफ़ॉक्स में काम नहीं किया! मुझे जो करना था circleवह gटैग में लपेट दिया गया था और translateयह ऊपर से उसी पोजीशनिंग फॉर्मूला का उपयोग कर रहा था । मैंने फिर टैग circleमें जोड़ा g, और इसके cxऔर cyमानों को सेट किया 0। वहां से, transform: scale(2)उम्मीद के मुताबिक केंद्र से स्केल होगा। अंतिम कोड इस तरह दिखता था।

this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('g')
  .attrs({
    class: d => `dot ${d.metric}`,
    transform: (d,i) => `translate(${valueScale(d.value) * Math.sin( sliceSize * i)} ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)})`
  })
  .append('circle')
  .attrs({
    r: this.opts.dotRadius,
    cx: 0,
    cy: 0,
  })

इस परिवर्तन को करने के बाद, मैंने जोड़ने circleके लिए .dot, अपने सीएसएस को बदले के लिए लक्षित किया transform: scale(2)। मुझे इसके उपयोग की आवश्यकता भी नहीं थी transform-origin

टिप्पणियाँ:

  1. मैं d3-selection-multiदूसरे उदाहरण में उपयोग कर रहा हूं । यह मुझे हर विशेषता के लिए .attrsदोहराने के बजाय एक ऑब्जेक्ट पास करने की अनुमति देता है .attr

  2. एक स्ट्रिंग टेम्पलेट शाब्दिक का उपयोग करते समय, पहले उदाहरण में सचित्र के रूप में लाइन-ब्रेक के बारे में पता होना चाहिए। इसमें आउटपुट में एक नई पंक्ति शामिल होगी और आपका कोड टूट सकता है।


2
शायद अगर आप ट्रांसफॉर्म-बॉक्स सेट करते हैं: फिल-बॉक्स; फ़ायरफ़ॉक्स जिस तरह से आप इसे चाहते थे काम किया होगा।
राबर्ट लोंगसन

कोशिश की है कि। काम करने का मन नहीं था। यह किया था काम करने के बाद मैं बदल svg:transform-origin.enabledफ़ायरफ़ॉक्स के दशक में वरी about:configपेज। लेकिन ... यह एक पर्याप्त समाधान की तरह प्रतीत नहीं हुआ। मुझे transform-origin: 50% 50%और के बीच एक विसंगति भी मिली transform-origin: center center
जेमी एस

svg.transform-origin.enabled pref को कई संस्करणों से पहले हटा दिया गया था। जब तक आप बहुत पुराने संस्करण का उपयोग कर रहे हैं, तब तक 50% और केंद्र के बीच कोई अंतर नहीं होना चाहिए। अगर फ़ायरफ़ॉक्स 59 या बाद में कोई अंतर है, तो बगज़िला बग को उठाने के लिए स्वतंत्र महसूस करें।
रॉबर्ट लोंगसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.