ฉันจะรับความกว้างและความสูงของผ้าใบ HTML5 ได้อย่างไร


99

ฉันจะรับความกว้างและความสูงขององค์ประกอบ canvas ใน JavaScript ได้อย่างไร

นอกจากนี้ "บริบท" ของผืนผ้าใบที่ฉันอ่านอยู่เสมอคืออะไร

คำตอบ:


131

มันอาจจะคุ้มค่าที่จะดูบทช่วยสอน: MDN Canvas Tutorial

คุณสามารถรับความกว้างและความสูงขององค์ประกอบผ้าใบได้ง่ายๆโดยการเข้าถึงคุณสมบัติเหล่านั้นขององค์ประกอบ ตัวอย่างเช่น:

var canvas = document.getElementById('mycanvas');
var width = canvas.width;
var height = canvas.height;

หากไม่มีแอตทริบิวต์ความกว้างและความสูงในองค์ประกอบ canvas ขนาดเริ่มต้น 300x150 จะถูกส่งกลับ หากต้องการรับความกว้างและความสูงที่ถูกต้องแบบไดนามิกให้ใช้รหัสต่อไปนี้:

const canvasW = canvas.getBoundingClientRect().width;
const canvasH = canvas.getBoundingClientRect().height;

หรือใช้ไวยากรณ์การทำลายโครงสร้างวัตถุที่สั้นกว่า:

const { width, height } = canvas.getBoundingClientRect();

contextเป็นวัตถุที่คุณได้รับจากผืนผ้าใบเพื่อช่วยให้คุณสามารถวาดเป็นมัน คุณสามารถคิดว่าcontextAPI เป็นผืนผ้าใบซึ่งให้คำสั่งที่ช่วยให้คุณสามารถวาดบนองค์ประกอบผ้าใบได้


โปรดทราบว่าบทช่วยสอน Mozilla นั้นเป็นลิงก์ที่ใช้งานไม่ได้ในตอนนี้ หวังว่าพวกเขาจะแก้ไขได้สักวัน
Sz.

1
สิ่งนี้ส่งคืนขนาดพื้นที่บริบทใน Chrome 31
shuji

12
สิ่งนี้ใช้ได้เฉพาะในกรณีที่widthและheightระบุโดยตรงเป็น<canvas />แอตทริบิวต์แท็ก
vladkras

5
นั่นไม่เป็นความจริง มันจะคืนค่าเสมอแม้ว่าจะไม่มีแอตทริบิวต์แท็กโดยมีค่าเริ่มต้นเป็น 300 x 150
Michael Theriot

โปรดทราบว่า getBoundingClientRect () บางครั้งรวมถึงเส้นขอบ สิ่งนี้อาจหรือไม่สำคัญ แต่ใน CSS ของฉันฉันตั้งค่าความกว้างและความสูงเป็น 100,100 และ getBoundingClientRect ส่งคืน 102, 102. clientHeight และ clientWidth (หรือ scrollHeight และ scrollWidth) ส่งคืน 100 อย่างถูกต้อง
DoomGo

38

คำตอบทั้งหมดก่อนหน้านี้ไม่ถูกต้องทั้งหมด เบราว์เซอร์หลัก 2 ตัวไม่รองรับคุณสมบัติ 2 ตัวนั้น (IE คือหนึ่งในนั้น) หรือใช้ต่างกัน

ทางออกที่ดีกว่า (รองรับโดยเบราว์เซอร์ส่วนใหญ่ แต่ฉันไม่ได้ตรวจสอบ Safari):

var canvas = document.getElementById('mycanvas');
var width = canvas.scrollWidth;
var height = canvas.scrollHeight;

อย่างน้อยฉันก็ได้รับค่าที่ถูกต้องด้วย scrollWidth และ -Height และต้องตั้งค่า canvas.width และ height เมื่อมีการปรับขนาด


ดูเหมือนว่า IE9 จะรองรับ canvas ความกว้างและความสูงได้ (รุ่นก่อนหน้า 9 ไม่รองรับ canvas เลย) ฉันเพิ่งลองใช้ไป คุณประสบปัญหาอะไร และเบราว์เซอร์หลักอื่น ๆ คืออะไร?
thomanski

1
ใช่ฉันไม่เคยอัปเดต IE เพราะฉันไม่ได้ใช้งาน เบราว์เซอร์หลักอื่น ๆ คือ Opera ซึ่งไม่ / ไม่อัปเดตความกว้างและความสูงขณะปรับขนาด
Bitterblue

2
canvas.width หรือ height อย่าส่งคืนขนาดทั้งหมดของผืนผ้าใบให้เลือก canvas.scrollWidth หรือ height เพื่อรับขนาดจริงทั้งหมดของผืนผ้าใบ
จอร์แดน

1
สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่คำตอบอื่นไม่ได้ผล ฉันกำลังมองหาวิธีแก้ปัญหาที่สามารถรับความกว้างและความสูงได้หากตั้งค่าผืนผ้าใบโดยใช้ bootstrap
wanderer0810

22

คำตอบที่กล่าวถึงcanvas.widthส่งคืนขนาดภายในของผืนผ้าใบกล่าวคือที่ระบุเมื่อสร้างองค์ประกอบ:

<canvas width="500" height="200">

หากคุณปรับขนาดผ้าใบด้วย CSS มิติข้อมูล DOM จะเข้าถึงได้ผ่านทาง.scrollWidthและ.scrollHeight:

var canvasElem = document.querySelector('canvas');
document.querySelector('#dom-dims').innerHTML = 'Canvas DOM element width x height: ' +
      canvasElem.scrollWidth +
      ' x ' +
      canvasElem.scrollHeight

var canvasContext = canvasElem.getContext('2d');
document.querySelector('#internal-dims').innerHTML = 'Canvas internal width x height: ' +
      canvasContext.canvas.width +
      ' x ' +
      canvasContext.canvas.height;

canvasContext.fillStyle = "#00A";
canvasContext.fillText("Distorted", 0, 10);
<p id="dom-dims"></p>
<p id="internal-dims"></p>
<canvas style="width: 100%; height: 123px; border: 1px dashed black">


นั่นคือคำตอบที่ถูกต้อง 2 มิติที่ต้องพิจารณา
Nadir

2
นี่ควรเป็นคำตอบที่เลือก direct widthand heightcall จะส่งคืน 300x150 เสมอหากคุณไม่ระบุค่าใด ๆ และใช้การปรับขนาดสัมพัทธ์ (ขณะใช้ bootstrap ... ขอบคุณ.
mcy

16

วัตถุบริบทช่วยให้คุณจัดการผืนผ้าใบ คุณสามารถวาดรูปสี่เหลี่ยมได้เช่นและอื่น ๆ อีกมากมาย

หากคุณต้องการรับความกว้างและความสูงคุณสามารถใช้แอตทริบิวต์ HTML มาตรฐานwidthและheight:

var canvas = document.getElementById( 'yourCanvasID' );
var ctx = canvas.getContext( '2d' );

alert( canvas.width );
alert( canvas.height ); 

3
คำตอบนี้ค่อนข้างเหมือนกันกับ @ andrewmu และจะไม่ได้ผลถ้าคุณปรับขนาดผ้าใบผ่าน CSS ดูคำตอบของฉันสำหรับโซลูชันที่มีประสิทธิภาพมากขึ้น
Dan Dascalescu

9

ตอนนี้เริ่มตั้งแต่ปี 2015 เบราว์เซอร์ทั้งหมด (หลัก ๆ ?) ดูเหมือนจะมีขนาดเล็กลงc.widthและc.heightได้รับขนาดภายในผ้าใบแต่:

คำถามที่เป็นคำตอบเป็นคำตอบที่ไม่สามารถนำไปใช้ได้เนื่องจากผ้าใบมีหลักการ 2 ขนาดที่แตกต่างกัน / อิสระ

"html" จะบอกว่า CSS width / height และของตัวเอง (attribute-) width / height

ดูตัวอย่างสั้น ๆ ของการปรับขนาดที่แตกต่างกันซึ่งฉันใส่ผ้าใบ 200/200 ลงในองค์ประกอบ 300/100 html

ด้วยตัวอย่างส่วนใหญ่ (ทั้งหมดที่ฉันเห็น) ไม่มีชุดขนาด css ดังนั้นพวกเขาจึงบอกเป็นนัยถึงความกว้างและความสูงของขนาดผ้าใบ (รูปวาด -) แต่นั่นไม่ใช่สิ่งที่จำเป็นและสามารถให้ผลลัพธ์ที่น่าสนุกได้หากคุณใช้ขนาดผิด - เช่น css widht / ความสูงสำหรับการวางตำแหน่งภายใน



0

นี่คือ CodePen ที่ใช้ canvas.height / width, CSS height / width และบริบทเพื่อแสดงผ้าใบทุกขนาดได้อย่างถูกต้อง

HTML:

<button onclick="render()">Render</button>
<canvas id="myCanvas" height="100" width="100" style="object-fit:contain;"></canvas>

CSS:

canvas {
  width: 400px;
  height: 200px;
  border: 1px solid red;
  display: block;
}

Javascript:

const myCanvas = document.getElementById("myCanvas");
const originalHeight = myCanvas.height;
const originalWidth = myCanvas.width;
render();
function render() {
  let dimensions = getObjectFitSize(
    true,
    myCanvas.clientWidth,
    myCanvas.clientHeight,
    myCanvas.width,
    myCanvas.height
  );
  myCanvas.width = dimensions.width;
  myCanvas.height = dimensions.height;

  let ctx = myCanvas.getContext("2d");
  let ratio = Math.min(
    myCanvas.clientWidth / originalWidth,
    myCanvas.clientHeight / originalHeight
  );
  ctx.scale(ratio, ratio); //adjust this!
  ctx.beginPath();
  ctx.arc(50, 50, 50, 0, 2 * Math.PI);
  ctx.stroke();
}

// adapted from: https://www.npmjs.com/package/intrinsic-scale
function getObjectFitSize(
  contains /* true = contain, false = cover */,
  containerWidth,
  containerHeight,
  width,
  height
) {
  var doRatio = width / height;
  var cRatio = containerWidth / containerHeight;
  var targetWidth = 0;
  var targetHeight = 0;
  var test = contains ? doRatio > cRatio : doRatio < cRatio;

  if (test) {
    targetWidth = containerWidth;
    targetHeight = targetWidth / doRatio;
  } else {
    targetHeight = containerHeight;
    targetWidth = targetHeight * doRatio;
  }

  return {
    width: targetWidth,
    height: targetHeight,
    x: (containerWidth - targetWidth) / 2,
    y: (containerHeight - targetHeight) / 2
  };
}

โดยทั่วไป canvas.height / width จะกำหนดขนาดของบิตแมปที่คุณกำลังแสดงผล จากนั้นความสูง / ความกว้าง CSS จะปรับขนาดบิตแมปให้พอดีกับพื้นที่เลย์เอาต์ (มักจะแปรปรวนเมื่อปรับขนาด) จากนั้นบริบทสามารถปรับเปลี่ยนมาตราส่วนเพื่อวาดโดยใช้การทำงานของเวกเตอร์ในขนาดต่างๆ


-1

ฉันมีปัญหาเนื่องจากผืนผ้าใบของฉันอยู่ในคอนเทนเนอร์ที่ไม่มีรหัสดังนั้นฉันจึงใช้โค้ด jquery ด้านล่างนี้

$('.cropArea canvas').width()

ฉันมักจะโพสต์เมื่อฉันใช้มัน .. ใครคืออัจฉริยะที่ลงคะแนนคำตอบของฉัน? อยากทราบว่า ..
Brian Sanchez

JQuery เป็นการพึ่งพาที่ยิ่งใหญ่สำหรับงานขนาดเล็กนี้
sdgfsdh

ฉันลองใช้ตัวเลือกที่ได้รับการโหวตแล้วและไม่ได้ผลสำหรับฉันฉันจึงโพสต์วิธีแก้ปัญหาของฉันเมื่อเขียนโค้ดสิ่งที่คุณต้องการคือเวลาเวลาคือทองคำดังนั้นทำไมไม่ใช้ jquery ?? .. น่าสนใจแล้วทำไมต้องลงคะแนน? ...
Brian Sanchez

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