css - لماذا ترتيب التحويلات يهم؟ SVG rotate/scale لا يعطي نفس النتيجة مثل scale/rotate




css3 css-transforms (2)

الطريقة التي أوضح تيماني عفيف اتباعها لأنظمة الإحداثيات التي تمتد كل عملية تحول. عليك أن تبدأ بمنفذ العرض ، ويتم اشتقاق كل نظام إحداثيات متتالي ويجلس في مكان مختلف على اللوحة القماشية. قد تتحول أنظمة الإحداثيات هذه إلى الديكارتي ("الكون الممدود"). يتم بناؤها في شجرة DOM من الخارج في ، وعندما بالسلاسل في سمة ، من اليسار إلى اليمين.

ولكن يمكنك أن تتخيل نفس التحول أيضًا في الاتجاه المعاكس ، من الداخل إلى الخارج: أولاً ، تقوم برسم مستطيل في نظام إحداثيات المستخدمين الديكارتيين الخاص بك ، ويمكنك تحويله من خلال سلسلة من المقاييس والدورانات وما إلى ذلك ، حتى عند رسمها في نظام تنسيق منفذ العرض ، يتم تشويهه إلى شيء آخر.

ولكن إذا نظرت إليها بالطريقة الثانية ، فيجب معالجة التحويلات المتسلسلة في إحدى السمات من اليمين إلى اليسار: transform: scale(2, 1) rotate(10deg) يعني أخذ مستطيل ، تدويره أولاً بـ 10deg ، ثم قياس المستطيل استدارة في الاتجاه الأفقي.

باختصار ، هذان متكافئان:

  • إذا قمت برسم صورة grafic في نظام إحداثيات محول ، فقم ببناء نظام الإحداثيات من خلال تطبيق التحويلات على أنظمة الإحداثيات هذه من اليسار إلى اليمين .
  • إذا قمت برسم تحويل grafic في نظام الإحداثيات الأصلي ، فبناء grafic عن طريق تطبيق التحويلات على grafic من اليمين إلى اليسار .

بعد التمشيط عبر مواصفات SVG ، وأدلة مثل this this ، ما زلت أكافح من أجل فهم بالضبط كيف تعمل سلسلة التسلسل.

ونقلت ذات الصلة مختارة

عندما تقوم بتطبيق سمة التحويل على عنصر SVG ، يحصل هذا العنصر على "نسخة" من نظام إحداثيات المستخدم الحالي قيد الاستخدام.

و:

عندما يتم تقييد التحويلات ، فإن الشيء الأكثر أهمية الذي يجب معرفته هو ، مثلما يحدث مع تحويلات عنصر HTML ، يتم تطبيق كل تحويل على نظام الإحداثيات بعد تحويل هذا النظام بواسطة التحويلات السابقة.

و:

على سبيل المثال ، إذا كنت ستطبق تناوبًا على عنصر ، متبوعًا بترجمة ، فستحدث الترجمة وفقًا لنظام الإحداثيات الجديد ، وليس النظام غير التناوب.

و:

تسلسل التحولات المسألة. تسلسل وظائف التحويل المحددة داخل سمة التحويل هو التسلسل الذي يتم تطبيقه على الشكل.

الشفرة

يتم تغيير نظام الإحداثيات الحالي للمستطيل الأول ، ثم تدويره (لاحظ الترتيب). يتم تدوير نظام الإحداثيات الحالي للمستطيل الثاني ، ثم تحجيمه.

svg {
  border: 1px solid green;
}
<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    rect#s1 {
      fill: red;
      transform: scale(2, 1) rotate(10deg);
    }
  </style>
  <rect id="s1" x="" y="" width="100" height="100" />
</svg>

<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    rect#s2 {
      fill: blue;
      transform: rotate(10deg) scale(2, 1);
    }
  </style>
  <rect id="s2" x="" y="" width="100" height="100" />
</svg>

سؤال

نحن نعلم أنه عندما نقوم بتحويل السلسلة ، يتم عمل نسخة من نظام الإحداثيات الحالي المستخدم لهذا العنصر ، ثم يتم تطبيق التحويلات بالترتيب المحدد لها.

عندما يكون لدينا نظام إحداثي مستخدم تم قياسه بالفعل ، ونطبق تدوير عليه ، يكون المستطيل منحرفًا بشكل فعال (كما هو موضح في الزوايا المتغيرة). لا يحدث هذا إذا قمنا بتحويل الاثنين في الاتجاه المعاكس (تدوير ، ثم التدرج).

مساعدة الخبراء بالضبط كيف يتم تدوير نظام الإحداثيات الحالي المقيس ، سيكون موضع تقدير عميق. أحاول أن أفهم ، من زاوية تقنية (أعمال داخلية) ، بالضبط سبب حدوث التنقيب في المستطيل الأول.

شكرا لكم.


لتوضيح كيفية عمله ، دعونا نفكر في رسم متحرك لإظهار كيف يغير تأثير التدرج التدوير.

.red {
  width:80px;
  height:20px;
  background:red;
  margin:80px;
  transform-origin:left center;
  animation: rotate 2s linear infinite;
}
@keyframes rotate {
  from{transform:rotate(0)}
  to{transform:rotate(360deg)}

}
<div class="container">
<div class="red">
</div>
</div>

كما ترون أعلاه ، فإن الدوران يخلق شكل دائرة مثالي.

الآن دعنا نوسع الحاوية ونرى الفرق:

.red {
  width:80px;
  height:20px;
  background:red;
  margin:80px;
  transform-origin:left center;
  animation: rotate 5s linear infinite;
}
@keyframes rotate {
  from{transform:rotate(0)}
  to{transform:rotate(360deg)}

}
.container {
  display:inline-block;
  transform:scale(3,1);
  transform-origin:left center;
}
<div class="container">
<div class="red">
</div>
</div>

لاحظ كيف لم يعد لدينا دائرة ولكنها القطع الناقص الآن. يبدو الأمر وكأننا أخذنا الدائرة ونقوم بإحداث تأثير انحراف داخل المستطيل لدينا.

إذا قمنا بالتأثير المعاكس وبدأنا بتأثير المقياس وبعد ذلك قمنا بتطبيق التناوب لن يكون لدينا أي تحريف.

.red {
  width:80px;
  height:20px;
  background:red;
  margin:80px;
  animation: rotate 2s linear infinite;
}
@keyframes rotate {
  from{transform:scale(1,1)}
  to{transform:scale(3,1)}

}
.container {
  display:inline-block;
  transform:rotate(30deg);
  transform-origin:left center;
}
<div class="container">
<div class="red">
</div>
</div>

لتوضيح الأمر بشكل مختلف: سيؤدي تطبيق الدوران إلى الحفاظ على نفس النسبة بين كل من المحور السيني والصادي حتى لا ترى أي تأثير سيء عند القيام بالتدريج لاحقًا ولكن التوسع في محور واحد فقط سوف يكسر النسبة وبالتالي يبدو شكلنا سيئًا عندما نحاول لتطبيق التناوب.

يمكنك التحقق من هذا الرابط إذا كنت تريد مزيدًا من التفاصيل حول كيفية ربط التحويل وكيف يتم مصفوفة: https://www.w3.org/TR/css-transforms-1/#transform-rendering . إنه يتعلق بعنصر HTML ولكن كما هو مذكور في مواصفات SVG ، فهو نفسه.

هنا الأجزاء ذات الصلة:

التحولات تراكمية. وهذا هو ، إنشاء عناصر نظام الإحداثيات المحلي الخاص بهم ضمن نظام الإحداثيات الخاص بوالدهم.

من وجهة نظر المستخدم ، يقوم العنصر بتجميع فعال لجميع خصائص تحويل أسلافه وكذلك أي تحويل محلي مطبق عليه

دعونا نفعل بعض الرياضيات من أجل معرفة الفرق بين كل من التحولات. دعنا نفكر في ضرب المصفوفة ولأننا نتعامل مع تحول خطي ثنائي الأبعاد ، فسنقوم بذلك على ℝ² من أجل البساطة 1 .

scale(2, 1) rotate(10deg) سيكون لدينا

 |2 0|   |cos(10deg) -sin(10deg)|   |2*cos(10deg) -2*sin(10deg) |
 |0 1| x |sin(10deg) cos(10deg) | = |1*sin(10deg) 1*cos(10deg)  |

الآن إذا طبقنا هذه المصفوفة على (Xi,Yi) (Xf,Yf) على (Xf,Yf) كما يلي:

 Xf = 2* (Xi*cos(10deg) - Yi*sin(10deg))
 Yf =     Xi*sin(10deg) + Yi*cos(10deg)

لاحظ كيف أن Xf لديه مُضاعِف إضافي وهو السبب في إنشاء تأثير الانحراف. يبدو أننا غيرنا السلوك أو Xf وأبقينا Yf

الآن لننظر في rotate(10deg) scale(2, 1) :

 |cos(10deg) -sin(10deg)|   |2 0|   |2*cos(10deg) -1*sin(10deg) |
 |sin(10deg) cos(10deg) | x |0 1| = |2*sin(10deg) 1*cos(10deg)  |

وبعد ذلك سيكون لدينا

 Xf =  2*Xi*cos(10deg) - Yi*sin(10deg)
 Yf =  2*Xi*sin(10deg) + Yi*cos(10deg)

يمكننا اعتبار 2*Xi كـ Xt ويمكننا القول أننا قمنا بتدوير عنصر ( Xt,Yi ) وتم تحجيم هذا العنصر في البداية بالنظر إلى المحور X.

1 يستخدم CSS أيضًا تحويل تقاربي (مثل الترجمة) ، لذا فإن استخدام ²² (الإحداثيات الديكارتية) لا يكفي لإجراء حسابنا لذلك نحن بحاجة إلى التفكير في ℝℙ² (الإحداثيات المتجانسة). حسابنا السابق سيكون:

 |2 0 0|   |cos(10deg) -sin(10deg) 0|   |2*cos(10deg) -2*sin(10deg) 0|
 |0 1 0| x |sin(10deg) cos(10deg)  0| = |1*sin(10deg) 1*cos(10deg)  0|
 |0 0 1|   |0          0           1|   |0            0             1|

لن يتغير أي شيء في هذه الحالة لأن الجزء الخاص بالباطل لاغٍ ولكن إذا كان لدينا ترجمة مقترنة بتحويل آخر (على سبيل المثال: scale(2, 1) translate(10px,20px) ) scale(2, 1) translate(10px,20px) على ما يلي:

 |2 0 0|   |1 0 10px|   |2 0 20px|
 |0 1 0| x |0 1 20px| = |0 1 20px|
 |0 0 1|   |0 0 1   |   |0 0  1  |

و

Xf =  2*Xi + 20px;
Yf =  Yi + 20px;
1  =  1 (to complete the multiplication) 




css-transforms