ฉันจะทำ svg scale ด้วย container parent ได้อย่างไร?


235

ฉันต้องการให้สเกลเนื้อหาขององค์ประกอบแบบอินไลน์ svg เมื่อขนาดไม่ใช่ภาษาท้องถิ่น แน่นอนว่าฉันสามารถแยกเป็นไฟล์และปรับให้เป็นแบบนั้นได้

index.html: <img src="foo.svg" style="width: 100%;" />

foo.svg: <svg width="123" height="456"></svg>

อย่างไรก็ตามฉันต้องการเพิ่มสไตล์เพิ่มเติมให้กับ SVG ผ่าน CSS ดังนั้นการลิงก์ภายนอกจะไม่ใช่ตัวเลือก ฉันจะสร้างสเกล SVG แบบอินไลน์ได้อย่างไร


2
ลอง precents ในความกว้างและความสูง SVG
ncm

@ncm มันจะทำอย่างไรกับ JS?
Mawg กล่าวว่าคืนสถานะโมนิก้า

คำตอบ:


457

ในการระบุพิกัดภายในรูปภาพ SVG โดยไม่ขึ้นกับขนาดที่ปรับขนาดของรูปภาพใช้แอviewBoxททริบิวต์ในองค์ประกอบ SVG เพื่อกำหนดว่ากล่องขอบเขตของรูปภาพอยู่ในระบบพิกัดของภาพอย่างไรและใช้widthและheightคุณลักษณะเพื่อกำหนดว่า ความกว้างหรือความสูงนั้นเกี่ยวกับหน้าที่มีอยู่

ตัวอย่างเช่นหากคุณมีสิ่งต่อไปนี้:

<svg>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

มันจะแสดงผลเป็นรูปสามเหลี่ยมขนาด 10px คูณ 20px:

สามเหลี่ยม 10x20

ตอนนี้ถ้าคุณตั้งค่าเฉพาะความกว้างและความสูงนั่นจะเปลี่ยนขนาดขององค์ประกอบ SVG แต่ไม่ปรับขนาดรูปสามเหลี่ยม:

<svg width=100 height=50>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

สามเหลี่ยม 10x20

หากคุณตั้งค่ากล่องมุมมองที่เป็นสาเหตุให้มันแปลงภาพเช่นนั้นกล่องที่กำหนด (ในระบบพิกัดของภาพ) จะถูกปรับขนาดให้พอดีกับความกว้างและความสูงที่กำหนด (ในระบบพิกัดของหน้า) ตัวอย่างเช่นหากต้องการไต่ระดับสามเหลี่ยมเป็น 100px คูณ 50px:

<svg width=100 height=50 viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

สามเหลี่ยม 100x50

หากคุณต้องการขยายให้กว้างตามความกว้างของวิวพอร์ต HTML:

<svg width="100%" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

รูปสามเหลี่ยมขนาด 300x150

โปรดทราบว่าโดยค่าเริ่มต้นอัตราส่วนภาพจะยังคงอยู่ ดังนั้นหากคุณระบุว่าองค์ประกอบควรมีความกว้าง 100% แต่ความสูง 50px จริง ๆ แล้วมันจะขยายความสูงได้ถึง 50px เท่านั้น (เว้นแต่คุณจะมีหน้าต่างแคบ ๆ ):

<svg width="100%" height="50px" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

สามเหลี่ยม 100x50

หากคุณต้องการยืดแนวนอนให้ปิดการใช้งานการคงอัตราส่วนไว้ด้วยpreserveAspectRatio=none:

<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

รูปสามเหลี่ยมขนาด 300x50

(โปรดทราบว่าในขณะที่ในตัวอย่างของฉันฉันใช้ไวยากรณ์ที่ใช้สำหรับการฝัง HTML เพื่อรวมตัวอย่างเป็นภาพใน StackOverflow ฉันแทนการฝังภายใน SVG อื่นดังนั้นฉันต้องใช้ไวยากรณ์ XML ที่ถูกต้อง)


1
คุณจะทำอย่างไรไม่เพียง แต่กล่องมุมมองที่สงวนไว้ SpectRatio แต่ยังเป็นกล่องหลัก? ฉันต้องการความกว้าง: 100%; ความสูง: อัตโนมัติสำหรับมัน
bjb568

1
@Dude: ฉันคิดว่าตัวอย่างที่มีwidth="100%"และไม่มีความสูงระบุเป็นสิ่งที่คุณต้องการ ฉันได้เพิ่มรูปภาพเพื่อสาธิต มันมีความกว้าง 100% และปรับความสูงตามสัดส่วน หากนั่นไม่ใช่สิ่งที่คุณกำลังมองหาคุณสามารถลองชี้แจงสิ่งที่คุณหมายถึงได้หรือไม่?
Brian Campbell

1
โอ้ ไม่มีปัญหาจริง มันเป็นเพียงข้อบกพร่องของ webkit ใน Safari และ Chrome ความสูง "ของจริง" คือ 100% ตามค่าเริ่มต้นไม่ใช่อัตโนมัติ ฉันจะแก้ไขสิ่งนี้ได้อย่างไร
bjb568

4
@ เพื่อน Ah ใช่ฉันเห็น ใช้งานได้ดีใน Firefox แต่ไม่มี Chrome หรือ Safari ตามข้อกำหนดของSVG Firefox ปรากฏว่าถูกต้อง ในขณะที่ค่าเริ่มต้นของwidthและheightสำหรับองค์ประกอบ SVG คือ 100% นี่ไม่ใช่คำนิยาม CSS ที่ 100% (100% ของบล็อกที่มี) แต่แทนที่จะเป็น 100% ของวิวพอร์ตที่ระบุตามอัตราส่วนที่แท้จริง ( ซึ่งคำนวณจากviewBoxเมื่อได้รับ) ฉันยังไม่พบวิธีแก้ปัญหาสำหรับปัญหานั้นใน Chrome / Safari
Brian Campbell

1
มันใช้งานได้สำหรับฉัน ฉันก่อนสร้างแอตทริบิวต์ viewBox ในองค์ประกอบ SVG และตั้งค่าเป็น "0 0 [ความกว้าง svg ดั้งเดิม] [ความสูง svg ดั้งเดิม]" ต่อไปฉันเปลี่ยนแอตทริบิวต์ความกว้างขององค์ประกอบ SVG เป็น "อัตโนมัติ" และแอตทริบิวต์ความสูงเป็น "100%" ภาชนะจะต้องมีความสูงที่กำหนด สเกลนี้ปรับขนาดเวกเตอร์เป็น 100% ของความสูงของคอนเทนเนอร์ซึ่งอนุญาตให้ความกว้างลอยได้ สุดท้ายตั้งค่าความกว้างสูงสุด CSS ของ SVG เป็น 100% เพื่อป้องกันการแก้ไขปัญหาคอนเทนเนอร์
Ryan Griggs

28

หลังจากผ่านการวิจัย 48 ชั่วโมงฉันก็ลงเอยด้วยการทำสิ่งนี้เพื่อให้ได้สัดส่วน:

หมายเหตุ: ตัวอย่างนี้เขียนด้วย React หากคุณไม่ได้ใช้สิ่งนั้นให้เปลี่ยนสิ่งที่เป็นตัวอูฐกลับไปเป็นเครื่องหมายยัติภังค์ (เช่น: เปลี่ยนbackgroundColorเป็นbackground-colorและเปลี่ยนสไตล์Objectกลับเป็น a String)

<div
  style={{
    backgroundColor: 'lightpink',
    resize: 'horizontal',
    overflow: 'hidden',
    width: '1000px',
    height: 'auto',
  }}
>
  <svg
    width="100%"
    viewBox="113 128 972 600"
    preserveAspectRatio="xMidYMid meet"
  >
    <g> ... </g>
  </svg>
</div>

นี่คือสิ่งที่เกิดขึ้นในโค้ดตัวอย่างด้านบน:

Viewbox

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox

min-x, min-y, width และ height

ie: viewbox = "0 0 1,000 1,000"

Viewbox เป็นคุณสมบัติที่สำคัญเพราะโดยทั่วไปจะบอก SVG ว่าขนาดใดที่จะวาดและตำแหน่ง หากคุณใช้ CSS เพื่อสร้าง SVG 1000x1000 px แต่ช่องมองภาพของคุณคือ 2000x2000 คุณจะเห็นไตรมาสบนซ้ายของ SVG ของคุณ

ตัวเลขสองตัวแรก min-x และ min-y พิจารณาว่าควรจะชดเชย SVG ภายในช่องมองภาพหรือไม่

SVG ของฉันต้องเลื่อนขึ้น / ลงหรือซ้าย / ขวา

ตรวจสอบสิ่งนี้: viewbox = "50 50 450 450"

ตัวเลขสองตัวแรกจะเปลี่ยน SVG ของคุณเหลือ 50px และสูงกว่า 50px และตัวเลขสองตัวที่สองคือขนาดช่องมองภาพ: 450x450 px หาก SVG ของคุณคือ 500x500 แต่มีช่องว่างภายในเพิ่มเติมบางส่วนคุณสามารถปรับเปลี่ยนตัวเลขเหล่านี้เพื่อย้ายไปรอบ ๆ ภายใน "ช่องมองภาพ"

เป้าหมายของคุณ ณ จุดนี้คือการเปลี่ยนหนึ่งในตัวเลขเหล่านั้นและดูว่าเกิดอะไรขึ้น

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

อัตราส่วนภาพคงที่

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio

จากการวิจัยของฉันมีจำนวนมากของการตั้งค่าอัตราส่วนที่แตกต่างกัน xMidYMid meetแต่อย่างหนึ่งเริ่มต้นที่เรียกว่า ฉันใส่มันลงไปเพื่อเตือนตัวเองอย่างชัดเจน xMidYMid meetทำให้ปรับขนาดตามสัดส่วนจุดกึ่งกลาง X และ Y ซึ่งหมายความว่าอยู่กึ่งกลางในช่องมองภาพ

ความกว้าง

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width

ดูโค้ดตัวอย่างของฉันด้านบน สังเกตว่าฉันตั้งค่าความกว้างเท่านั้นไม่สูง ฉันตั้งค่าเป็น 100% ดังนั้นจึงเต็มคอนเทนเนอร์ที่มีอยู่นี่คือสิ่งที่อาจเป็นประโยชน์มากที่สุดในการตอบคำถาม Stack Overflow นี้

คุณสามารถเปลี่ยนเป็นค่าพิกเซลที่คุณต้องการได้ แต่ฉันขอแนะนำให้ใช้ 100% เหมือนที่ฉันทำเพื่อเพิ่มขนาดสูงสุดแล้วควบคุมด้วย CSS ผ่านคอนเทนเนอร์หลัก ฉันแนะนำสิ่งนี้เพราะคุณจะได้รับการควบคุม "เหมาะสม" คุณสามารถใช้คิวรีสื่อและคุณสามารถควบคุมขนาดได้โดยไม่ต้องใช้ JavaScript ที่บ้า

การปรับขนาดด้วย CSS

ดูโค้ดตัวอย่างของฉันด้านบนอีกครั้ง สังเกตว่าฉันมีคุณสมบัติเหล่านี้อย่างไร:

resize: 'horizontal', // you can safely omit this
overflow: 'hidden',   // if you use resize, use this to fix weird scrollbar appearance
width: '1000px',
height: 'auto',

นี่เป็นสิ่งเพิ่มเติม แต่จะแสดงวิธีให้ผู้ใช้ปรับขนาด SVG ในขณะที่รักษาอัตราส่วนภาพที่เหมาะสม เนื่องจาก SVG รักษาอัตราส่วนของตัวเองไว้คุณจะต้องปรับขนาดความกว้างบนคอนเทนเนอร์หลักและปรับขนาดตามที่ต้องการ

เราปล่อยให้ความสูงเพียงอย่างเดียวและ / หรือตั้งค่าเป็นอัตโนมัติและเราควบคุมการปรับขนาดด้วยความกว้าง ฉันเลือกความกว้างเพราะมักจะมีความหมายมากกว่าเนื่องจากการออกแบบที่ตอบสนองได้ดี

นี่คือรูปภาพของการตั้งค่าเหล่านี้ที่ใช้งานอยู่:

ป้อนคำอธิบายรูปภาพที่นี่

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

https://css-tricks.com/scale-svg/

มันเป็นบทความที่มีขนาดใหญ่ แต่มันก็แยกย่อยทุกวิธีที่เป็นไปได้ในการจัดการ SVG โดยมีหรือไม่มี CSS ฉันแนะนำให้อ่านขณะดื่มกาแฟหรือของเหลวที่คุณเลือก


ดูเหมือนจะไม่ทำงานกับ SVG ใด ๆ - หากคุณไม่สามารถควบคุมแหล่งที่มาของ SVG ได้วิธีนี้จะล้มเหลวเมื่อ SVG มีความกว้างคงที่
user48956

@ user48956 คุณสามารถจัดการมันได้ตลอดเวลาด้วย JavaScript
แอนดรู

ใช่ - คุณสามารถกระตุ้นรูปแบบไฟล์ต่างๆด้วยการเขียนโปรแกรมได้ตลอดเวลา แต่คุณหวังว่าจะมีวิธีการที่เหมาะกับเนื้อหาทุกประเภท (เช่น PNG) และไม่จำเป็นต้องใช้โปรแกรมจาวาสคริปต์
user48956

21

คุณจะต้องทำการแปลงเช่น:

ด้วย JavaScript:

document.getElementById(yourtarget).setAttribute("transform", "scale(2.0)");

ด้วย CSS:

#yourtarget {
  transform:scale(2.0);
  -webkit-transform:scale(2.0);
}

ล้อมหน้า SVG ของคุณในแท็กกลุ่มเช่นนี้และกำหนดเป้าหมายเพื่อจัดการทั้งหน้า:

<svg>
  <g id="yourtarget">
    your svg page
  </g>
</svg>

หมายเหตุ : ระดับ 1.0 คือ 100%


7
ตกลง. ฉันไม่ต้องการ JS ในสิ่งนี้ มีวิธีที่จะให้มันพอดีกับพ่อแม่หรือไม่?
bjb568

@bj setAttribute เหมือนกันกับ <tag attribute = "value">
john ktejik

17

ล้อเล่นไปรอบ ๆ และพบ CSS นี้ดูเหมือนว่าจะมี SVG ในเบราว์เซอร์ Chrome จนถึงจุดที่คอนเทนเนอร์มีขนาดใหญ่กว่ารูปภาพ:

div.inserted-svg-logo svg { max-width:100%; }

ดูเหมือนว่าจะทำงานใน FF + IE 11 ด้วย


วิธีนี้แก้ไขปัญหาสำหรับฉัน ฉันเห็นการล้นใน iOS เท่านั้น ขอบคุณ!
Evan Mattson

5
การใช้ทั้งสองmax-width: 100%และmax-height: 100%จะทำให้ svg ปรับขนาดไปยังคอนเทนเนอร์เสมอโดยไม่ล้นหรือทำให้อัตราส่วนภาพลดลง
Gavin

2
@ กาวินmax-height: 100%ไม่ทำงานสำหรับฉันแก้ไขโดยใช้vhแทน%
Pavel

2

การเปลี่ยนไฟล์ SVG ไม่ใช่วิธีแก้ปัญหาที่เป็นธรรมสำหรับฉันดังนั้นฉันใช้หน่วย CSS ที่เกี่ยวข้องแทน

vh, vw, %มีประโยชน์มาก ฉันใช้ CSS ต้องการheight: 2.4vh;ตั้งค่าขนาดไดนามิกเป็นภาพ SVG ของฉัน



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.