ปรับขนาด SVG (Raphael.js) เหมือน SWF

ฉันเริ่มใช้ Raphael.js เมื่อไม่กี่วันก่อน และฉันก็สนุกกับมันมาก สิ่งเดียวที่ฉันไม่สามารถเข้าใจได้คือวิธีรับแท็ก "กระดาษ" หรือ svg/vml เพื่อเติมเต็มหน้าต่างเบราว์เซอร์เช่น swf ดูตัวอย่างนี้

สังเกตวิธีที่ตัวอย่างด้านบนปรับขนาดด้วยหน้าต่างเบราว์เซอร์

ฉันสามารถรับ "กระดาษ" เพื่อปรับขนาดด้วยหน้าต่างเบราว์เซอร์ได้ แต่ไม่มีโชคในการปรับขนาดกราฟิกแบบเวกเตอร์ทั้งหมด ข้อเสนอแนะใด ๆ ที่จะได้รับการชื่นชมอย่างมาก

แก้ไข

ฉันลองใช้เส้นทางที่แตกต่างกันมากมายกับสิ่งนี้ viewBox ใช้งานได้ดีแต่เป็น SVG เท่านั้น ฉันเพิ่งหาวิธีทำได้โดยใช้ชุด Raphael และโค้ดเล็กๆ น้อยๆ ในเหตุการณ์ window.onresize ฉันจะโพสต์สิ่งที่ฉันค้นพบภายหลังคืนนี้หรือพรุ่งนี้ ฉันยังอยากเห็นวิธีแก้ปัญหาอื่น ๆ สำหรับคำถามนี้ถ้ามี


person Zevan    schedule 01.12.2010    source แหล่งที่มา


คำตอบ (5)


ฉันใช้เวลาสักครู่ แต่ในที่สุดฉันก็สามารถแก้ไขปัญหานี้ได้ ฉันได้รวมโซลูชันไว้ในไฟล์ js ขนาดเล็กที่สามารถใช้กับ Raphael ได้ คุณสามารถรับไฟล์ js พร้อมกับเอกสารประกอบง่ายๆ ได้ที่นี่ ดูการทำงานจริง

วิธีการทำงาน:

  1. ใช้ viewBox สำหรับ svg
  2. ล้อมโหนด vml ทั้งหมดในโหนดกลุ่ม
  3. ล้อมคอนสตรัคเตอร์ Raphael ขึ้นเพื่อให้โหนดกลุ่ม vml ถูกส่งผ่านไปยังคอนสตรัคเตอร์ Raphael
  4. แก้ไขคุณสมบัติ CSS บางอย่างเมื่อปรับขนาดกระดาษเพื่อจัดการกับการจัดกึ่งกลาง การตัด และการรักษาอัตราส่วนภาพที่ถูกต้อง

ข้อเสนอแนะใด ๆ ที่จะได้รับการชื่นชมอย่างมาก

person Zevan    schedule 04.12.2010
comment
คุณสามารถมี ScaleRaphael ได้เพียงอินสแตนซ์เดียวเท่านั้นหรือไม่? ... ฉันกำลังใส่ไฟล์ .svg ลงในภาพขนาดย่อ ... .svg ดั้งเดิมมีขนาดประมาณ 400x400 แต่ขนาดหัวแม่มือคือ 75x75 ... ฉันใช้อินสแตนซ์เฉพาะของ Raphael( container_id ) สำหรับแต่ละนิ้วหัวแม่มือ ... แต่ดูเหมือนว่าเมื่อฉันเปลี่ยนไปใช้ new ScaleRaphael( container_id , 75, 75) นิ้วหัวแม่มือทั้งหมดจะรวมเป็นองค์ประกอบภาพเดียว - person dsdsdsdsd; 04.11.2013

สวัสดีเซวาน

ฉันพบคำตอบดีๆ จากผู้ชายชื่อเซวาน อย่างไรก็ตาม ฉันพบว่าโค้ดนั้นซับซ้อนเกินไปสำหรับความชอบของฉัน (ต้องใช้ jquery ทำสิ่งแปลก ๆ เช่น "$(this)" ฯลฯ )

ดังนั้นฉันจึงทำให้มันง่ายขึ้น ตอนนี้สั้นพอที่จะใส่ลงใน stackoverflow ;):

var paper;

window.ScaleRaphael = function(container, width, height) {
    var wrapper = document.getElementById(container);
    wrapper.style.width = width + "px";
    wrapper.style.height = height + "px";
    wrapper.style.overflow = "hidden";

    wrapper.innerHTML = "<div id='svggroup'><\/div>";
    var nestedWrapper = document.getElementById("svggroup");

    paper = new Raphael(nestedWrapper, width, height);
    paper.w = width;
    paper.h = height;
    paper.canvas.setAttribute("viewBox", "0 0 "+width+" "+height);
    paper.changeSize = function() {
        var w = window.innerWidth
        var h = window.innerHeight
        var ratioW = w / width;
        var ratioH = h / height;
        var scale = ratioW < ratioH ? ratioW : ratioH;

        var newHeight = Math.floor(height * scale);
        var newWidth = Math.floor(width * scale);

        wrapper.style.width = newWidth + "px";
        wrapper.style.height = newHeight + "px";
        paper.setSize(newWidth, newHeight);
    }
    window.onresize = function() {
        paper.changeSize();
    }

    paper.changeSize();

    return paper;
}

ข้อเสียเปรียบเพียงอย่างเดียวจากเวอร์ชันของคุณคือต้องใช้ SVG แต่ไม่ได้ใช้ VML นี่เป็นปัญหาหรือไม่?

ฉันใช้มันกับหน้าสาธิตเวอร์ชันที่เรียบง่ายของคุณ:

<!DOCTYPE html> 
<html lang="en"> 
<head>
<title>ScaleRaphaël Demo 1</title>
<meta charset="utf-8"> 

<script type="text/javascript" src="raphael.js"></script>
<script type="text/javascript" src="scale.raphael.js"></script>
<script type="text/javascript">

    window.onload = function() {
        var paper = new ScaleRaphael("wrap", 600, 400);

        // draw some random vectors:
        var path = "M " + paper.w / 2 + " " + paper.h / 2;
        for (var i = 0; i < 100; i++){
            var x = Math.random() * paper.w;
            var y = Math.random() * paper.h;
            paper.circle(x, y,
                Math.random() * 60 + 2).
                attr("fill", "rgb("+Math.random() * 255+",0,0)").
                attr("opacity", 0.5);
            path += "L " + x + " " + y + " ";
        }

        paper.path(path).attr("stroke","#ffffff").attr("stroke-opacity", 0.2);

        paper.text(200,100,"Resize the window").attr("font","30px Arial").attr("fill","#ffffff");
    }

      </script>
<style type="text/css">
    body, html {
        margin: 0;
        padding: 0;
        overflow: hidden;
    }

    #wrap{
        background-color: orange;
    }
</style>

</head>
<body>

person Community    schedule 13.06.2011
comment
ฉันรู้ว่าคุณไม่ได้รองรับ vml นั่นเป็นเหตุผลว่าทำไมฟังก์ชันการปรับขนาดของคุณจึงไม่ถูกตั้งค่าสำหรับ IE สำหรับฉัน ส่วนสำคัญของ Raphael คือการรองรับ VML... ดังนั้นวิธีการปรับขนาดหน้าต่างจึงจำเป็นต้องทำงานใน IE - person Zevan; 14.06.2011
comment
คำตอบและรหัสที่ยอดเยี่ยม สิ่งนี้ช่วยฉันได้มากจากการลองผิดลองถูกจำนวนมหาศาล ขอบคุณ! - person Adam Crossland; 25.10.2011

คุณสามารถวนซ้ำเส้นทางทั้งหมดและปรับขนาด () ตามขนาดใหม่ของกระดาษหลังจากปรับขนาดแล้ว

person Gipsy King    schedule 01.12.2010
comment
ปรากฎว่าไม่จำเป็นต้องวนซ้ำหากคุณใช้ set และทำ myset.scale(2,2,0,0) - person Zevan; 02.12.2010
comment
@Zeven น่าสนใจ! ฉันไม่ได้ดูฉากต่างๆ ตอนที่ฉันใช้ราฟาเอล - person Gipsy King; 02.12.2010
comment
ฉันได้พูดคุยด้วยเร็ว ๆ นี้แม้ว่า น่าเสียดายหากคุณปรับขนาดชุดของวัตถุ ระบบพิกัดจะไม่ถูกรักษาไว้ ซึ่งอาจทำให้ภาพเคลื่อนไหวที่อาจเกิดขึ้นเสียหายได้ ความหมายการเปลี่ยนแปลง cx และ cy ขึ้นอยู่กับขนาด ฉันค่อนข้างแน่ใจว่าสิ่งนี้สามารถหลีกเลี่ยงได้หาก Raphael ใช้สิ่งแปลง () SVG ไม่แน่ใจว่าเหตุใดจึงทำการปรับขนาดด้วยตนเองแทนที่จะใช้ฟังก์ชัน SVG ในตัว อาจมีบางอย่างเกี่ยวกับการมีโค้ดที่เข้ากันได้กับ VML ได้อย่างง่ายดาย ฉันจะคอยดูมันต่อไป กรณีที่เลวร้ายที่สุด ฉันจะเขียนปลั๊กอินบางประเภท - person Zevan; 02.12.2010

คุณสามารถเพิ่มแอตทริบิวต์ 'viewBox' บนองค์ประกอบรูท svg เพื่อกำหนด ระบบพิกัดรูปร่างก็จะปรับขนาดตามขนาดของคอนเทนเนอร์ ไม่แน่ใจว่าจะจัดการกับด้าน VML ของสิ่งต่าง ๆ อย่างไร ฉันขอแนะนำให้รายงานปัญหา https://github.com/DmitryBaranovskiy/raphael/issues.

person Erik Dahlström    schedule 01.12.2010
comment
เยี่ยมเลย ฉันจะลองดู - และฉันจะพิจารณาด้าน VML ของสิ่งต่าง ๆ - person Zevan; 01.12.2010
comment
มันใช้งานได้ดีจริงๆ ดูเหมือนว่าสิ่งที่เทียบเท่าใน VML คือการล้อมวัตถุทั้งหมดในโหนดกลุ่ม ฉันทำสิ่งนี้และมันก็ใช้งานได้ดีจริงๆ ปัญหาเดียวคือราฟาเอลไม่สามารถเติมหรือจัดสไตล์วัตถุได้อีกต่อไป ฉันเดาว่าเป็นเพราะการเปลี่ยนแปลงโครงสร้าง VML - person Zevan; 02.12.2010
comment
ฉันเดาว่าใน IE ความกว้างและความสูงของกระดาษสามารถตั้งค่าเป็นนิพจน์ที่คำนวณขนาดขององค์ประกอบหลัก - person Spadar Shut; 17.07.2011

นี่อาจจะเก่าเกินไปสำหรับเธรด แต่อย่างน้อย Raphael 2.0 ก็มีวิธี setViewBox -- http://raphaeljs.com/reference.html#Paper.setViewBox

คุณยังคงต้องตั้งค่าขนาดแคนวาสจริงเป็น 100% ดังนั้น คอนเทนเนอร์ จึงปรับขนาดตามหน้าต่าง แต่การเรียก setViewBox ด้วย w/h ที่เหมาะสมใน window.resize callback ของคุณน่าจะช่วยได้

person drzaus    schedule 21.01.2013
comment
นี่เป็นตัวอย่างสุ่มแบบเก่าที่เท่าเทียมกันของการใช้ setViewBox เพื่อซูมบน mousewheel - jsfiddle.net/9zu4U/2 - person drzaus; 21.01.2013