it-swarm.dev

كيفية استخدام مؤشر z في عناصر SVG؟

أنا أستخدم دوائر svg في مشروعي مثل هذا ،

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
    <g>
        <g id="one">
            <circle fill="green" cx="100" cy="105" r="20" />
        </g>
        <g id="two">
            <circle fill="orange" cx="100" cy="95" r="20" />
        </g>
    </g>
</svg>

وأنا أستخدم الفهرس z في علامة g لإظهار العناصر أولاً. في مشروعي ، أحتاج إلى استخدام قيمة الفهرس z فقط ، لكن لا يمكنني استخدام الفهرس z لعناصر svg الخاصة بي. لقد غوغل كثيرا ولكن لم أجد أي شيء نسبيا. لذا ، الرجاء مساعدتي في استخدام z-index في svg الخاص بي.

هنا هو تجريبي.

125
karthik

تخصيص

في إصدار مواصفات SVG 1.1 ، يعتمد ترتيب العرض على ترتيب المستند:

first element -> "painted" first

الرجوع إلى SVG 1.1. تخصيص

3.3 تقديم الطلب

تحتوي العناصر الموجودة في جزء مستند SVG على ترتيب رسم ضمني ، مع الحصول على {العناصر الأولى في جزء مستند SVG "رسمت" أولاً. يتم رسم العناصر اللاحقة على رأس العناصر التي تم رسمها مسبقًا.


محلول (منظف أسرع)

يجب وضع الدائرة الخضراء كأحدث كائن يتم رسمه. حتى مبادلة العنصرين.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120"> 
   <!-- First draw the orange circle -->
   <circle fill="orange" cx="100" cy="95" r="20"/> 

   <!-- Then draw the green circle over the current canvas -->
   <circle fill="green" cx="100" cy="105" r="20"/> 
</svg>

هنا شوكة الخاص بك jsFiddle .

الحل (بديل)

العلامة use مع السمة xlink:href وقيمة معرف العنصر. ضع في اعتبارك أنه قد لا يكون أفضل حل حتى لو كانت النتيجة جيدة. بعد قليل من الوقت ، هنا رابط المواصفات SVG 1.1 "استخدم" العنصر .

غرض:

لتجنب مطالبة المؤلفين بتعديل المستند المشار إليه لإضافة معرف إلى العنصر الجذر.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120">
    <!-- First draw the green circle -->
    <circle id="one" fill="green" cx="100" cy="105" r="20" />
    
    <!-- Then draw the orange circle over the current canvas -->
    <circle id="two" fill="orange" cx="100" cy="95" r="20" />
    
    <!-- Finally draw again the green circle over the current canvas -->
    <use xlink:href="#one"/>
</svg>

ملاحظات على SVG 2

مواصفات SVG 2 هو الإصدار الرئيسي التالي ولا يزال يدعم الميزات المذكورة أعلاه.

3.4. تقديم الطلب

يتم وضع العناصر في SVG في ثلاثة أبعاد. بالإضافة إلى موضعها على محور x و y في منفذ عرض SVG ، يتم وضع عناصر SVG أيضًا على المحور z. الموضع على المحور z يحدد الترتيب المرسوم به.

على طول المحور z ، {يتم تجميع العناصر في سياقات التراص.}

3.4.1. تأسيس سياق التراص في SVG

...

سياقات التراص هي أدوات مفاهيمية تستخدم لـ {وصف الترتيب الذي يجب أن ترسم فيه العناصر واحدة فوق الأخرى عندما يتم تقديم المستند ، ...

135
Maicolpt

حاول قلب #one و #two. ألقِ نظرة على هذا الكمان: http://jsfiddle.net/hu2pk/3/

Update

في SVG ، يتم تعريف z-index بالترتيب الذي يظهر به العنصر في المستند . يمكنك إلقاء نظرة على هذه الصفحة أيضًا إذا كنت تريد: https://stackoverflow.com/a/482147/1932751

26
Lucas Willems

كما قال الآخرون هنا ، يتم تعريف z-index بالترتيب الذي يظهر به العنصر في DOM. إذا لم يكن إعادة ترتيب html يدويًا خيارًا أو سيكون من الصعب ، فيمكنك استخدام D3 لإعادة ترتيب مجموعات/كائنات SVG.

استخدم D3 لتحديث ترتيب DOM وتقليد وظائف فهرس Z

تحديث مؤشر SVG Element Z مع D3

على المستوى الأساسي (وإذا كنت لا تستخدم معرفات لأي شيء آخر) ، يمكنك استخدام معرفات العناصر كقاعدة احتياطية لفهرسة z وإعادة ترتيبها. أبعد من ذلك يمكنك أن تدع خيالك يسير إلى حد كبير.

أمثلة في مقتطف الشفرة

var circles = d3.selectAll('circle')
var label = d3.select('svg').append('text')
                                                .attr('transform', 'translate(' + [5,100] + ')')

var zOrders = {
        IDs: circles[0].map(function(cv){ return cv.id; }),
    xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
    yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
    radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
    customOrder: [3, 4, 1, 2, 5]
}

var setOrderBy = 'IDs';
var setOrder = d3.descending;

label.text(setOrderBy);
circles.data(zOrders[setOrderBy])
circles.sort(setOrder);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 100"> 
  <circle id="1" fill="green" cx="50" cy="40" r="20"/> 
  <circle id="2" fill="orange" cx="60" cy="50" r="18"/>
  <circle id="3" fill="red" cx="40" cy="55" r="10"/> 
  <circle id="4" fill="blue" cx="70" cy="20" r="30"/> 
  <circle id="5" fill="pink" cx="35" cy="20" r="15"/> 
</svg>

الفكرة الأساسية هي:

  1. استخدم D3 لتحديد عناصر SVG DOM.

    var circles = d3.selectAll('circle')
    
  2. قم بإنشاء مجموعة من مؤشرات z باستخدام علاقة 1: 1 بعناصر SVG (التي تريد إعادة ترتيبها). صفائف الفهرس Z المستخدمة في الأمثلة أدناه هي معرفات ، موضع x & y ، نصف قطر ، إلخ ...

    var zOrders = {
        IDs: circles[0].map(function(cv){ return cv.id; }),
        xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
        yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
        radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
        customOrder: [3, 4, 1, 2, 5]
    }
    
  3. ثم ، استخدم D3 لربط مؤشرات z الخاصة بك بهذا التحديد.

    circles.data(zOrders[setOrderBy]);
    
  4. أخيرًا ، اتصل بـ D3.sort لإعادة ترتيب العناصر في DOM بناءً على البيانات.

    circles.sort(setOrder);
    

أمثلة

 enter image description here 

  • يمكنك المكدس بواسطة معرف

 enter image description here 

  • مع أقصى اليسار SVG على القمة

 enter image description here 

  • أصغر دائرة نصف قطرها في الأعلى

 enter image description here 

  • أو حدد مصفوفة لتطبيق الفهرس z لترتيب معين - في المثال الخاص بي ، تقوم الصفيفة [3,4,1,2,5] بنقل/إعادة ترتيب الدائرة الثالثة (بترتيب HTML الأصلي) لتكون الأولى في DOM ، الرابعة إلى الثانية ، الأولى لتكون الثالث ، وهلم جرا ...

21
Steve Ladavich

يمكنك استخدام استخدام .

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
    <g>
        <g id="one">
            <circle fill="green" cx="100" cy="105" r="20" />
        </g>
        <g id="two">
            <circle fill="orange" cx="100" cy="95" r="20" />
        </g>
    </g>
    <use xlink:href="#one" />
</svg>

تظهر الدائرة الخضراء في الأعلى.
jsFiddle

19
Jose Rui Santos

لا يوجد مؤشر z ل svgs. لكن svg يحدد أي من العناصر الخاصة بك هي الأعلى من حيث موضعه في DOM. وبالتالي يمكنك إزالة الكائن ووضعه في نهاية svg مما يجعله العنصر "الأخير الذي تم تقديمه". ثم يتم تقديم هذا واحد "الأعلى" بصريا.


باستخدام jQuery:

function moveUp(thisObject){
    thisObject.appendTo(thisObject.parents('svg>g'));
}

الاستعمال:

moveUp($('#myTopElement'));

استخدام D3.js:

d3.selection.prototype.moveUp = function() {
    return this.each(function() {
        this.parentNode.appendChild(this);
    });
};

الاستعمال:

myTopElement.moveUp();

9
Hafenkranich

كما تمت مناقشته ، يتم تقديم svgs بالترتيب ولا يأخذ مؤشر z في الاعتبار (في الوقت الحالي). ربما فقط أرسل العنصر المحدد إلى أسفل الأصل الخاص به حتى يتم عرضه.

function bringToTop(targetElement){
  // put the element at the bottom of its parent
  let parent = targetElement.parentNode;
  parent.appendChild(targetElement);
}

// then just pass through the element you wish to bring to the top
bringToTop(document.getElementById("one"));

عملت لي.

تحديث

إذا كان لديك SVG متداخل ، يحتوي على مجموعات ، فستحتاج إلى إخراج العنصر من العقدة الأصل.

function bringToTopofSVG(targetElement){
  let parent = targetElement.ownerSVGElement;
  parent.appendChild(targetElement);
}

ميزة لطيفة في SVG هي أن كل عنصر يحتوي على موقعه بغض النظر عن المجموعة المتداخلة فيه: +1:

8
bumsoverboard

باستخدام D3:

إذا كنت تريد إضافة العنصر بترتيب عكسي إلى استخدام البيانات:

.insert('g', ":first-child")

بدلا من .append

إضافة عنصر إلى أعلى عنصر المجموعة

7
Nathan Hensher

باستخدام D3:

إذا كنت ترغب في إعادة إدراج كل عنصر محدد ، بالترتيب ، كآخر تابع لوالده.

selection.raise()
6
Diso

سيكون الحل الآخر هو استخدام divs ، والتي تستخدم zIndex لاحتواء عناصر SVG. كما يلي: https://stackoverflow.com/a/28904640/4552494

5
Roman Rekhler

الحلول النظيفة والسريعة والسهلة التي تم نشرها اعتبارًا من تاريخ هذه الإجابة غير مرضية. وهي مبنية على البيان المعيب بأن وثائق SVG تفتقر إلى ترتيب z. المكتبات ليست ضرورية أيضا. يمكن لسطر واحد من التعليمات البرمجية إجراء معظم العمليات لمعالجة ترتيب z للكائنات أو مجموعات من الكائنات التي قد تكون مطلوبة في تطوير تطبيق ينقل الكائنات ثنائية الأبعاد في مساحة x-y-z.

ترتيب Z موجود بالتأكيد في أجزاء مستند SVG

ما يسمى جزء وثيقة SVG هو شجرة من العناصر المشتقة من نوع العقدة الأساسية SVGElement. العقدة الجذرية لجزء وثيقة SVG هي SVGSVGElement ، والتي تتوافق مع HTML5 <svg> tag. يتوافق SVGGElement مع العلامة <g> ويسمح بتجميع الأطفال.

إن امتلاك سمة z-index على SVGElement كما في CSS من شأنه أن يهزم نموذج تقديم SVG. ينص القسمان 3.3 و 3.4 من التوصية W1C SVG v1.1 الإصدار الثاني على أن أجزاء وثيقة SVG (أشجار النسل من SVGSVGElement) يتم تقديمها باستخدام ما يسمى _ ​​البحث الأول بعمق عن الشجرة). هذا المخطط هو ترتيب z بكل معنى الكلمة.

ترتيب Z هو في الواقع اختصار رؤية الكمبيوتر لتجنب الحاجة إلى عرض ثلاثي الأبعاد حقيقي مع التعقيدات ومتطلبات الحوسبة للبحث عن الأشعة. المعادلة الخطية للفهرس z الضمني للعناصر في جزء مستند SVG.

z-index = z-index_of_svg_tag + depth_first_tree_index / tree_node_qty

هذا مهم لأنه إذا كنت تريد نقل دائرة أقل من مربع إلى أعلى ، فيمكنك ببساطة إدراج المربع قبل الدائرة. يمكن القيام بذلك بسهولة في JavaScript.

طرق الدعم

تحتوي مثيلات SVGElement على طريقتين تدعمان معالجة أوامر z البسيطة والبسيطة.

  • parent.removeChild (الطفل)
  • الوالدين. إدراج قبل (الطفل ، الطفل)

الإجابة الصحيحة التي لا تنشئ فوضى

نظرًا لأنه يمكن إزالة SVGGElement ( <g> tag) وإدراجها بنفس السهولة مثل SVGCircleElement أو أي شكل آخر ، يمكن تطبيق طبقات الصور النموذجية لمنتجات Adobe وأدوات الرسومات الأخرى بسهولة باستخدام SVGGElement. جافا سكريبت هي في الأساس تحريك أدناه قيادة.

parent.insertBefore(parent.removeChild(gRobot), gDoorway)

إذا كانت طبقة الروبوت مرسومة كأولاد لـ SVGGElement gRobot قبل المدخل المرسوم كأولاد لـ SVGGElement gDoorway ، أصبح الروبوت الآن خلف المدخل لأن ترتيب z الخاص بالمدخل أصبح الآن واحدًا بالإضافة إلى ترتيب z للروبوت.

A نقل أعلاه الأمر يكاد يكون سهلاً.

parent.insertBefore(parent.removeChild(gRobot), gDoorway.nextSibling())

مجرد التفكير في a = a و b = b لتذكر هذا.

insert after = move above
insert before = move below

ترك DOM في حالة متوافقة مع طريقة العرض

السبب في صحة هذه الإجابة هو أنها ضئيلة وكاملة ، كما هو الحال في منتجات Adobe الداخلية أو غيرها من برامج تحرير الرسومات المصممة بشكل جيد ، تترك التمثيل الداخلي في حالة تتسق مع العرض الذي تم إنشاؤه بواسطة العرض.

النهج البديل ولكن المحدود

هناك طريقة أخرى شائعة الاستخدام وهي استخدام CSS z-index جنبًا إلى جنب مع أجزاء وثيقة SVG متعددة (علامات SVG) مع خلفيات شفافة في الغالب في الجزء السفلي. مرة أخرى ، هذا يهزم أناقة طراز تقديم SVG ، مما يجعل من الصعب تحريك الكائنات لأعلى أو لأسفل بالترتيب z.


ملاحظات:

  1. ( https://www.w3.org/TR/SVG/render.html v 1.1 ، الإصدار الثاني ، 16 أغسطس 2011)

    3.3 تجسيد عناصر الطلب في جزء مستند SVG له ترتيب رسم ضمني ، مع "رسم" العناصر الأولى في جزء مستند SVG أولاً. يتم رسم العناصر اللاحقة على رأس العناصر التي تم رسمها مسبقًا.

    3-4 كيف يتم تقديم المجموعات ، يكون لعناصر التجميع مثل العنصر "g" (انظر عناصر الحاوية) تأثير إنتاج لوحة منفصلة مؤقتة تم تهيئتها باللون الأسود الشفاف والتي يتم رسم العناصر عليها. عند الانتهاء من المجموعة ، يتم تطبيق أي تأثيرات مرشح محددة للمجموعة لإنشاء لوحة قماش مؤقتة تم تعديلها. يتم تركيب اللوحة القماشية المؤقتة المعدلة في الخلفية ، مع مراعاة أي إعدادات إخفاء وتعتيم على مستوى المجموعة في المجموعة.

3
Douglas Daseeco

لدينا بالفعل 2019 ولا يزال z-index غير مدعوم في SVG.

يمكنك أن ترى على الموقع دعم SVG2 في Mozilla حالة z-index - لم يتم التنفيذ.

يمكنك أيضًا الاطلاع على الموقع الخطأ 360148 "دعم خاصية 'z-index' على عناصر SVG" (تم الإبلاغ عنها: منذ 12 عامًا).

لكن لديك 3 احتمالات في SVG لتعيينها:

  1. مع element.appendChild(aChild);
  2. مع parentNode.insertBefore(newNode, referenceNode);
  3. مع targetElement.insertAdjacentElement(positionStr, newElement); (لا يوجد دعم في IE لـ SVG)

مثال تجريبي تفاعلي

مع كل هذا 3 وظائف.

var state = 0,
    index = 100;

document.onclick = function(e)
{
    if(e.target.getAttribute('class') == 'clickable')
    {
        var parent = e.target.parentNode;

        if(state == 0)
            parent.appendChild(e.target);
        else if(state == 1)
            parent.insertBefore(e.target, null); //null - adds it on the end
        else if(state == 2)
            parent.insertAdjacentElement('beforeend', e.target);
        else
            e.target.style.zIndex = index++;
    }
};

if(!document.querySelector('svg').insertAdjacentElement)
{
    var label = document.querySelectorAll('label')[2];
    label.setAttribute('disabled','disabled');
    label.style.color = '#aaa';
    label.style.background = '#eee';
    label.style.cursor = 'not-allowed';
    label.title = 'This function is not supported in SVG for your browser.';
}
label{background:#cef;padding:5px;cursor:pointer}
.clickable{cursor:pointer}
With: 
<label><input type="radio" name="check" onclick="state=0" checked/>appendChild()</label>
<label><input type="radio" name="check" onclick="state=1"/>insertBefore()</label><br><br>
<label><input type="radio" name="check" onclick="state=2"/>insertAdjacentElement()</label>
<label><input type="radio" name="check" onclick="state=3"/>Try it with z-index</label>
<br>
<svg width="150" height="150" viewBox="0 0 150 150">
    <g stroke="none">
        <rect id="i1" class="clickable" x="10" y="10" width="50" height="50" fill="#80f"/>
        <rect id="i2" class="clickable" x="40" y="40" width="50" height="50" fill="#8f0"/>
        <rect id="i3" class="clickable" x="70" y="70" width="50" height="50" fill="#08f"/>
    </g>
</svg>
3
Bharata

اضغط على عنصر SVG حتى يدوم ، بحيث يكون مؤشر z الخاص به في الأعلى. في SVG ، لا توجد خاصية تسمى z-index. حاول أدناه جافا سكريبت لإحضار العنصر إلى الأعلى.

var Target = document.getElementById(event.currentTarget.id);
var svg = document.getElementById("SVGEditor");
svg.insertBefore(Target, svg.lastChild.nextSibling);

الهدف: هو عنصر نحتاج إلى جعله أعلى svg: هو حاوية العناصر

2
Vaseem AbdulSamad

من السهل القيام بذلك:

  1. استنساخ البنود الخاصة بك
  2. فرز العناصر المستنسخة
  3. استبدال العناصر بواسطة المستنسخة
function rebuildElementsOrder( selector, orderAttr, sortFnCallback ) {
        let $items = $(selector);
        let $cloned = $items.clone();
        
        $cloned.sort(sortFnCallback != null ? sortFnCallback : function(a,b) {
                let i0 = a.getAttribute(orderAttr)?parseInt(a.getAttribute(orderAttr)):0,
                    i1 = b.getAttribute(orderAttr)?parseInt(b.getAttribute(orderAttr)):0;
                return i0 > i1?1:-1;
        });

        $items.each(function(i, e){
            e.replaceWith($cloned[i]);
        })
}

$('use[order]').click(function() {
    rebuildElementsOrder('use[order]', 'order');

    /* you can use z-index property for inline css declaration
    ** getComputedStyle always return "auto" in both Internal and External CSS decl [tested in chrome]
    
    rebuildElementsOrder( 'use[order]', null, function(a, b) {
        let i0 = a.style.zIndex?parseInt(a.style.zIndex):0,
                    i1 = b.style.zIndex?parseInt(b.style.zIndex):0;
                return i0 > i1?1:-1;
    });
    */
});
use[order] {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="keybContainer" viewBox="0 0 150 150" xml:space="preserve">
<defs>
    <symbol id="sym-cr" preserveAspectRatio="xMidYMid meet" viewBox="0 0 60 60">
        <circle cx="30" cy="30" r="30" />
        <text x="30" y="30" text-anchor="middle" font-size="0.45em" fill="white">
            <tspan dy="0.2em">Click to reorder</tspan>
        </text>
    </symbol>
</defs>
    <use order="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="0" y="0" width="60" height="60" style="fill: #ff9700; z-index: 1;"></use>
    <use order="4" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="50" y="20" width="50" height="50" style="fill: #0D47A1; z-index: 4;"></use>
    <use order="5" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="15" y="30" width="50" height="40" style="fill: #9E9E9E; z-index: 5;"></use>
    <use order="3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="25" y="30" width="80" height="80" style="fill: #D1E163; z-index: 3;"></use>
    <use order="2" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="30" y="0" width="50" height="70" style="fill: #00BCD4; z-index: 2;"></use>
    <use order="0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="5" y="5" width="100" height="100" style="fill: #E91E63; z-index: 0;"></use>
</svg>
0
tdjprog