আপনি এইচটিএমএল ক্যানভাসে পাঠ্যের উচ্চতা কীভাবে খুঁজে পাবেন?


148

অনুমানটির একটি প্রসঙ্গ আছে me পরিমাপের পাঠ (পাঠ্য) ফাংশন যা আপনাকে জানাবে যে সেই পাঠ্যটি মুদ্রণের জন্য কত প্রস্থের প্রয়োজন হবে, তবে এটি কতটা লম্বা তা খুঁজে পাওয়ার কোনও উপায় আমি খুঁজে পাচ্ছি না। আমি জানি এটি ফন্টের উপর ভিত্তি করে, তবে আমি কোনও ফন্টের স্ট্রিংটিকে একটি পাঠ্যের উচ্চতায় রূপান্তর করতে জানি না।


1
আমি উপরের উত্তরের চেয়ে ভাল উপায় জানতে পছন্দ করব। যদি স্বেচ্ছাচারী পয়েন্ট ফন্ট নিতে এবং এতে সর্বাধিক / মিনিটের সীমাটি খুঁজে পেতে কিছু অ্যালগরিদম থাকে তবে আমি এটি সম্পর্কে শুনে খুব খুশি হব। =)
বেটগ্যামিট

@tjameson - আছে বলে মনে হচ্ছে। এলিস্ববেন থেকে উত্তর দেখুন (এবং এটিতে আমার বৃদ্ধি)।
ড্যানিয়েল আরউইকার

2
আমি ভাবছি যে ইউনিকোড চরিত্রের 'ফুল ব্লক' (ইউ + 2588) এর প্রস্থটিকে দুটি দিয়ে গুণ করে প্রায় অনুমান হিসাবে ব্যবহার করা যেতে পারে?
ড্যানিয়েল এফ

1
এটি লক্ষণীয় যে উত্তরটি আপনার প্রয়োজনীয়তার উপর কিছুটা নির্ভর করে। উদাহরণস্বরূপ, "ক" অক্ষরটি রেন্ডার করার জন্য প্রয়োজনীয় উচ্চতা হ'ল অক্ষরের রেন্ডার করার জন্য প্রয়োজনীয় উচ্চতা থেকে আলাদা, y ফন্টের বেসলাইনের নীচে প্রসারিত কারণে। নীচের এইচটিএমএল ভিত্তিক উত্তরগুলি এর জন্য অ্যাকাউন্ট করে না এবং আপনাকে কোনও পাঠ্যের জন্য উপযুক্ত একটি উচ্চতা দেয়, তবে @ নোটিডার্টের উত্তর নির্দিষ্ট পাঠ্যের জন্য আরও সঠিক উচ্চতা দেয়।
ডেল অ্যান্ডারসন

2
মনে রাখবেন আপনার এমন চরিত্র থাকতে পারে যা দেখতে দেখতে M̶̢̹̝͖̦̖̭͕̭̣͆̃̀̅̒̊͌̿ͅতাই এটি সত্যিই জটিল সমস্যা তাই সাধারণ ক্ষেত্রে সমাধান করুন।
০৯

উত্তর:


78

আপডেট - এই কাজের উদাহরণের জন্য, আমি ক্যারোটার সম্পাদকটিতে এই কৌশলটি ব্যবহার করেছি ।

Ellisbben এর উত্তর থেকে অনুসরণ করে এখানে বেসলাইন, অর্থাত্ হিসাবে একই থেকে চড়াই এবং বংশদ্ভুত পেতে একটি বর্ধিত সংস্করণ tmAscentএবং tmDescentWin32 এর দ্বারা ফিরে GetTextMetric API- টি। আপনি যদি বিভিন্ন ফন্ট / আকারের স্প্যানগুলির সাথে একটি শব্দ-মোড়ানো পাঠ্য করতে চান তবে এটি প্রয়োজন needed

মেট্রিক লাইনের সাথে ক্যানভাসে বড় পাঠ্য

উপরের চিত্রটি সাফারিতে একটি ক্যানভাসে তৈরি হয়েছিল, লালটি শীর্ষ লাইন যেখানে ক্যানভাসটি পাঠ্যটি আঁকতে বলা হয়েছিল, সবুজটি বেসলাইন এবং নীলের নীচে নীল (তাই লাল থেকে নীল পুরো উচ্চতা)।

সংযুক্তি জন্য jQuery ব্যবহার:

var getTextHeight = function(font) {

  var text = $('<span>Hg</span>').css({ fontFamily: font });
  var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');

  var div = $('<div></div>');
  div.append(text, block);

  var body = $('body');
  body.append(div);

  try {

    var result = {};

    block.css({ verticalAlign: 'baseline' });
    result.ascent = block.offset().top - text.offset().top;

    block.css({ verticalAlign: 'bottom' });
    result.height = block.offset().top - text.offset().top;

    result.descent = result.height - result.ascent;

  } finally {
    div.remove();
  }

  return result;
};

একটি পাঠ্য উপাদান ছাড়াও, আমি একটি ডিভ যুক্ত display: inline-blockকরি যাতে আমি এটি সেট করতে পারিvertical-align স্টাইলটি এবং তারপরে ব্রাউজারটি কোথায় রেখেছিল তা সন্ধান করতে পারি।

সুতরাং আপনি কোনও বস্তুর সাথে ফিরে আসবেন ascent, descentএবং height(যা সুবিধার জন্য মাত্র ascent+ descent)। এটি পরীক্ষা করতে, এটি একটি ফাংশন যা মূল্য অনুভূমিক রেখা আঁকতে পারে তা মূল্যবান:

var testLine = function(ctx, x, y, len, style) {
  ctx.strokeStyle = style; 
  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x + len, y);
  ctx.closePath();
  ctx.stroke();
};

তারপরে আপনি দেখতে পারবেন কীভাবে টেক্সটটি উপরে, বেসলাইন এবং নীচে সম্পর্কিত ক্যানভাসে অবস্থান করছে:

var font = '36pt Times';
var message = 'Big Text';

ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top'; // important!
ctx.font = font;
ctx.fillText(message, x, y);

// Canvas can tell us the width
var w = ctx.measureText(message).width;

// New function gets the other info we need
var h = getTextHeight(font);

testLine(ctx, x, y, w, 'red');
testLine(ctx, x, y + h.ascent, w, 'green');
testLine(ctx, x, y + h.height, w, 'blue');

3
উচ্চতা নির্ধারণ করতে এই পাঠ্যটি ব্যবহার করবেন না কেন? abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ফন্টের উপর নির্ভর করে আপনার জি এবং এম এর চেয়ে অনেক বেশি বা কম অক্ষর থাকতে পারে
ওমেটেস

1
@ এলিস্ব্বেবেন এটি লক্ষ করার মতো যে এর ফলাফলগুলি আপনার থেকে কিছুটা পৃথক, যদিও আমি জানি না। উদাহরণস্বরূপ, আপনার কুরিয়ার নিউ 8pt ==> 12 পিক্সেল উচ্চ বলেছে, যখন এটিতে বলেছেন: কুরিয়ার নিউ 8pt ==> 13 পিক্সেল উচ্চ। আমি আপনার পদ্ধতিতে "জি" যুক্ত করেছি, তবে এটির পার্থক্য ছিল না। একটি আশ্চর্য, কোন মানটি সবচেয়ে কার্যকর হবে (প্রযুক্তিগতভাবে অগত্যা সঠিক নয়)।
ওড়ওলোফিল

3
যখন আমি প্রথম লাইন পরিবর্তিত আমি শুধু সঠিকভাবে কাজ কিছু পেতে পারে getTextHeight()থেকে var text = $('<span>Hg</span>').css({ 'font-family': fontName, 'font-size' : fontSize });, অর্থাত্ আকার আলাদাভাবে যোগ।
ক্যামেরন.ব্রাকেন

1
এটি অ-ইংরাজী পাঠ্যের জন্য কীভাবে কাজ করবেন? দেখতে jsfiddle.net/siddjain/6vURk
মর্ফিয়াস

1
ধন্যবাদ ! খুব দীর্ঘ স্ট্রিং পরিচালনা <div></div>করতে পরিবর্তন করুন<div style="white-space : nowrap;"></div>
মিকৈল গউভিন

40

মূলধন এম এর দৈর্ঘ্য পরীক্ষা করে আপনি উলম্ব উচ্চতার খুব কাছাকাছি অনুমান করতে পারেন

ctx.font='bold 10px Arial';

lineHeight=ctx.measureText('M').width;

8
প্রস্থটি কীভাবে আমাদের রেখার উচ্চতার একটি সীমাবদ্ধতা দেয়?
রিচার্ড বার্কার

11
তারা মানে একটি প্রদত্ত ফন্টের আকার একটি একক রাজধানী 'এম' প্রস্থ যে সম্পর্কে লাইনের উচ্চতা হিসাবে একই। (এটি সত্য কিনা তা জানেন না তবে উত্তরটি কী বলছে তা নিশ্চিত করে)
নাথান

2
এটি আসলে বেশ শালীন অনুমান যা আমি দ্রুত প্রোটোটাইপিংয়ের জন্য ব্যবহার করি। এটি নিখুঁত নয়, তবে এটি 90% সমাধান।
অস্টিন ডি

37

ক্যানভাস স্পেক স্ট্রিংয়ের উচ্চতা পরিমাপের জন্য আমাদের কোনও পদ্ধতি দেয় না। তবে, আপনি আপনার পাঠ্যের আকারটি পিক্সেলে সেট করতে পারেন এবং আপনি সাধারণত উল্লম্ব চৌম্বকটি তুলনামূলকভাবে সহজে কী তা নির্ধারণ করতে পারেন।

আপনার যদি আরও সুনির্দিষ্ট কিছু প্রয়োজন হয় তবে আপনি পাঠ্যটি ক্যানভাসে ফেলে দিতে পারেন এবং তারপরে পিক্সেল ডেটা পেতে পারেন এবং কতগুলি পিক্সেল উল্লম্বভাবে ব্যবহার করা হয়েছে তা নির্ধারণ করতে পারেন। এটি তুলনামূলকভাবে সহজ হবে, তবে খুব দক্ষ নয়। আপনি এটির মতো কিছু করতে পারেন (এটি কাজ করে তবে আপনার ক্যানভাসে এমন কিছু পাঠ্য আঁকবে যা আপনি সরাতে চান):

function measureTextHeight(ctx, left, top, width, height) {

    // Draw the text in the specified area
    ctx.save();
    ctx.translate(left, top + Math.round(height * 0.8));
    ctx.mozDrawText('gM'); // This seems like tall text...  Doesn't it?
    ctx.restore();

    // Get the pixel data from the canvas
    var data = ctx.getImageData(left, top, width, height).data,
        first = false, 
        last = false,
        r = height,
        c = 0;

    // Find the last line with a non-white pixel
    while(!last && r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                last = r;
                break;
            }
        }
    }

    // Find the first line with a non-white pixel
    while(r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                first = r;
                break;
            }
        }

        // If we've got it then return the height
        if(first != r) return last - first;
    }

    // We screwed something up...  What do you expect from free code?
    return 0;
}

// Set the font
context.mozTextStyle = '32px Arial';

// Specify a context and a rect that is safe to draw in when calling measureTextHeight
var height = measureTextHeight(context, 0, 0, 50, 50);
console.log(height);

বেসপিনের জন্য তারা একটি ছোট 'মি' প্রস্থের পরিমাপ করে উচ্চতা নকল করে ... আমি জানি না এটি কীভাবে ব্যবহৃত হয়, এবং আমি এই পদ্ধতির সুপারিশ করব না। এখানে প্রাসঙ্গিক বেসপিন পদ্ধতি:

var fixCanvas = function(ctx) {
    // upgrade Firefox 3.0.x text rendering to HTML 5 standard
    if (!ctx.fillText && ctx.mozDrawText) {
        ctx.fillText = function(textToDraw, x, y, maxWidth) {
            ctx.translate(x, y);
            ctx.mozTextStyle = ctx.font;
            ctx.mozDrawText(textToDraw);
            ctx.translate(-x, -y);
        }
    }

    if (!ctx.measureText && ctx.mozMeasureText) {
        ctx.measureText = function(text) {
            ctx.mozTextStyle = ctx.font;
            var width = ctx.mozMeasureText(text);
            return { width: width };
        }
    }

    if (ctx.measureText && !ctx.html5MeasureText) {
        ctx.html5MeasureText = ctx.measureText;
        ctx.measureText = function(text) {
            var textMetrics = ctx.html5MeasureText(text);

            // fake it 'til you make it
            textMetrics.ascent = ctx.html5MeasureText("m").width;

            return textMetrics;
        }
    }

    // for other browsers
    if (!ctx.fillText) {
        ctx.fillText = function() {}
    }

    if (!ctx.measureText) {
        ctx.measureText = function() { return 10; }
    }
};

28
আমি সন্দেহ করি যে এইচটিএমএল 5 স্পাই লিখেছেন এমন লোকেরা মনে মনে রেখেছিল।
স্টিভ হ্যানভ

17
এটি একটি ভয়ানক ভয়ঙ্কর হ্যাক যা আমি একেবারে পছন্দ করি। +1
আল্লায় লালোন্ডে

1
আমি পাই না। "এম" বর্ণের প্রস্থের প্রস্থের প্রস্থের মধ্যে সংযোগটি কোথায়?
কায়াহর

6
emএকটি আপেক্ষিক ফন্ট পরিমাপ যেখানে একটি Mইমেল ডিফল্ট ফন্টের আকারের অক্ষরের উচ্চতার সমান ।
জেরন

1
ঠিক আছে, উচ্চতা প্রস্থ নয় ... আমি এখনও সংযোগ সম্পর্কে বিভ্রান্ত। এছাড়াও, আমি মনে করি যে ইএমএসগুলি অপ্রাসঙ্গিক বলে দেওয়া হয়েছে যে আমরা কেবল পিক্সেলের উচ্চতা সম্পর্কে যত্নশীল।
Prestaul

35

ব্রাউজারগুলি উন্নত পাঠ্য মেট্রিকগুলিকে সমর্থন করতে শুরু করেছে , এটি যখন ব্যাপকভাবে সমর্থিত হয় তখন এই টাস্কটিকে নগণ্য করে তুলবে:

let metrics = ctx.measureText(text);
let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

fontHeightস্ট্রিংটি রেন্ডার করা নির্বিশেষে ধীরে ধীরে আপনি বাউন্ডিং বক্সের উচ্চতা পান। actualHeightস্ট্রিংটি রেন্ডার হওয়ার সাথে সম্পর্কিত।

স্পেস: https://www.w3.org/TR/2012/CR-2dcontext-20121217/#dom-textmetics-fontboundingboxascent এবং এর ঠিক নীচে বিভাগগুলি।

সমর্থন স্থিতি (20-আগস্ট -2017):


2
এই বৈশিষ্ট্যগুলি শীঘ্রই কার্যকর করার জন্য সবাই দয়া করে বাগের পৃষ্ঠাগুলিতে ভোট দিন
জেরেমিয়া রোজ

21

সম্পাদনা: আপনি কি ক্যানভাস রূপান্তর ব্যবহার করছেন? যদি তা হয় তবে আপনাকে রূপান্তর ম্যাট্রিক্স ট্র্যাক করতে হবে। নিম্নলিখিত রূপটি প্রাথমিক ট্রান্সফর্মের সাহায্যে পাঠ্যের উচ্চতা পরিমাপ করা উচিত।

সম্পাদনা # 2: অদ্ভুতভাবে নীচের কোডটি যখন আমি এই স্ট্যাকওভারফ্লো পৃষ্ঠায় এটি চালিত করি তখন সঠিক উত্তর উত্পন্ন হয় না; এটি সম্পূর্ণরূপে সম্ভব যে কিছু স্টাইলের নিয়মের উপস্থিতি এই ফাংশনটিকে ভেঙে দিতে পারে।

ক্যানভাস সিএসএস দ্বারা সংজ্ঞায়িত ফন্টগুলি ব্যবহার করে, তাই তত্ত্ব হিসাবে আমরা কেবলমাত্র নথিতে একটি উপযুক্ত স্টাইলযুক্ত টুকরো যোগ করতে পারি এবং এর উচ্চতা পরিমাপ করতে পারি। আমি মনে করি এটি পাঠ্য রেন্ডারিং এবং তারপরে পিক্সেল ডেটা পরীক্ষা করার চেয়ে উল্লেখযোগ্যভাবে সহজ এবং এটি আরোহী এবং বংশধরদেরও সম্মান করা উচিত। নিম্নলিখিতটি দেখুন:

var determineFontHeight = function(fontStyle) {
  var body = document.getElementsByTagName("body")[0];
  var dummy = document.createElement("div");
  var dummyText = document.createTextNode("M");
  dummy.appendChild(dummyText);
  dummy.setAttribute("style", fontStyle);
  body.appendChild(dummy);
  var result = dummy.offsetHeight;
  body.removeChild(dummy);
  return result;
};

//A little test...
var exampleFamilies = ["Helvetica", "Verdana", "Times New Roman", "Courier New"];
var exampleSizes = [8, 10, 12, 16, 24, 36, 48, 96];
for(var i = 0; i < exampleFamilies.length; i++) {
  var family = exampleFamilies[i];
  for(var j = 0; j < exampleSizes.length; j++) {
    var size = exampleSizes[j] + "pt";
    var style = "font-family: " + family + "; font-size: " + size + ";";
    var pixelHeight = determineFontHeight(style);
    console.log(family + " " + size + " ==> " + pixelHeight + " pixels high.");
  }
}

আপনাকে এটি নিশ্চিত করতে হবে যে আপনি ডিওএম উপাদানটির ফন্টের শৈলীটি সঠিকভাবে পেয়েছেন যেটির উচ্চতা আপনি পরিমাপ করেন তবে এটি বেশ সোজা; সত্যিই আপনার মতো কিছু ব্যবহার করা উচিত

var canvas = /* ... */
var context = canvas.getContext("2d");
var canvasFont = " ... ";
var fontHeight = determineFontHeight("font: " + canvasFont + ";");
context.font = canvasFont;
/*
  do your stuff with your font and its height here.
*/

1
+1 উপায় আরও ভাল সমাধান আইএমও। বেসলাইনটির পাশাপাশি পজিশন পাওয়াও উচিত।
ড্যানিয়েল আরউইকার

একটি উত্তর যুক্ত করেছেন যা বেসলাইন পায়।
ড্যানিয়েল আরউইকার

এটা কি কাজ করে? এমনকি এটি একটি ডিভের সাথে লেগে থাকার বিষয়ে আমি ভাবিনি। এটি সম্ভবত ডিওমে যোগ করতে হবে না, না?
24-30 '

নোডের নথির অংশ না হয়ে কোন আকার এবং অবস্থানের ক্ষেত্র বিদ্যমান তা সম্পর্কে আমি সম্পূর্ণ অজ্ঞ। আমি এমন একটি রেফারেন্স পড়তে খুব আগ্রহী যেটি যদি সেই ঠিকানাটিকে সম্বোধন করে, যদি আপনি কারও সম্পর্কে জানেন।
ellisbben

5
স্ক্রিনফুল জটিল জটিল কোডের জন্য +1 যা কেবল প্রসঙ্গ হবে
asure পরিমাপের

11

আপনি যদি পংক্তিতে লেখার উচ্চতা ফন্টের আকারের (পিটিএসে) এর সমান না?



সাধারণ ক্ষেত্রে: আপনি সর্বদা উচ্চারণকে ফন্টের নাম থেকে পার্স করতে পারেন: parseInt (ctx.font.split ('') [0] .রেপ্লেস ('px', '')); // পার্সিং স্ট্রিং: "10px ভার্ডানা"
শান

আপনি ফন্ট আকারের জন্য px, pt, em এবং% ব্যবহার করতে পারেন। ঠিক এই কারণেই এই উত্তরটি বিভ্রান্তিকর।
জ্যাকসনকর

@ জ্যাকসনকর, হ্যাঁ তবে তবুও আপনি সেগুলি পার্স করতে পারেন এবং ঠিক সেই অনুযায়ী ঠিক করতে পারেন? বা এই পদ্ধতির কোথাও অন্তর্নিহিত সীমাবদ্ধতা আছে?
পেসারিয়ার

@ পেসারিয়ার সীমাবদ্ধতা হ'ল আপনি এমন কিছু বাগ প্রবর্তন করতে পারেন যা আপনাকে চুলগুলি টেনে আনার কারণ করে। কেবল মনে রাখবেন যে ইউনিট প্রকারের মিশ্রণের ফলে বগি / স্প্যাগেটি কোড হতে পারে। এটি বলেছে, যতক্ষণ সমস্যাগুলির ঝুঁকি কম থাকে ততক্ষণ আমি মাঝেমধ্যে হ্যাকের উপরে নেই।
জ্যাকসনকর

10

জেজে স্টিফের পরামর্শ অনুসারে, আপনি আপনার পাঠ্যকে একটি স্প্যানে যুক্ত করতে পারেন এবং তারপরে স্প্যানের অফসেটহাইট পরিমাপ করতে পারেন।

var d = document.createElement("span");
d.font = "20px arial";
d.textContent = "Hello world!";
document.body.appendChild(d);
var emHeight = d.offsetHeight;
document.body.removeChild(d);

এইচটিএমএল 5 রকসে প্রদর্শিত


3
এটি খুব সুন্দর সমাধান, ধন্যবাদ ... তবে কেন জানি না যদি এই স্প্যানটি পৃষ্ঠাতে যুক্ত না করা এবং আমি এটির অফসাইট হাইট পাওয়ার আগে দৃশ্যমান হত! এটি সর্বদা ক্রোম এবং ফায়ারফক্সে জিরো হিসাবে উচ্চতা ফিরিয়ে দেয়!
মোস্তফাহ

1
আপনি ঠিক বলেছেন, আমার ধারণা, জায়গা নেওয়ার জন্য এটি ডোমে যুক্ত করতে হবে। এখানে এই কাজের একটি জেএস ফ্রিডল : jsfiddle.net/mpalmerlee/4NfVR/4 আমি উপরের কোডটিও আপডেট করেছি।
ম্যাট Palmerlee

ক্লায়েন্টহাইট ব্যবহার করাও এক সম্ভাবনা। যদিও এই উত্তরটি সমস্যার সমাধান, এটি একটি কুৎসিত কাজ work তবুও এটি +1 করেছে।
ড্যানিয়েল এফ

এটি দৃশ্যমান পাঠ্যের প্রকৃত উচ্চতা বিবেচনা করে না এবং সাধারণত পাঠ্যের শীর্ষে অতিরিক্ত মার্জিন নিয়ে আসে ...
আইন তোহভরি

8

ড্যানিয়েলের উত্তরে (যা দুর্দান্ত! এবং একেবারে ঠিক!), JQuery ব্যতীত সংস্করণ যুক্ত করতে:

function objOff(obj)
{
    var currleft = currtop = 0;
    if( obj.offsetParent )
    { do { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
      while( obj = obj.offsetParent ); }
    else { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
    return [currleft,currtop];
}
function FontMetric(fontName,fontSize) 
{
    var text = document.createElement("span");
    text.style.fontFamily = fontName;
    text.style.fontSize = fontSize + "px";
    text.innerHTML = "ABCjgq|"; 
    // if you will use some weird fonts, like handwriting or symbols, then you need to edit this test string for chars that will have most extreme accend/descend values

    var block = document.createElement("div");
    block.style.display = "inline-block";
    block.style.width = "1px";
    block.style.height = "0px";

    var div = document.createElement("div");
    div.appendChild(text);
    div.appendChild(block);

    // this test div must be visible otherwise offsetLeft/offsetTop will return 0
    // but still let's try to avoid any potential glitches in various browsers
    // by making it's height 0px, and overflow hidden
    div.style.height = "0px";
    div.style.overflow = "hidden";

    // I tried without adding it to body - won't work. So we gotta do this one.
    document.body.appendChild(div);

    block.style.verticalAlign = "baseline";
    var bp = objOff(block);
    var tp = objOff(text);
    var taccent = bp[1] - tp[1];
    block.style.verticalAlign = "bottom";
    bp = objOff(block);
    tp = objOff(text);
    var theight = bp[1] - tp[1];
    var tdescent = theight - taccent;

    // now take it off :-)
    document.body.removeChild(div);

    // return text accent, descent and total height
    return [taccent,theight,tdescent];
}

আমি উপরের কোডটি সবেমাত্র পরীক্ষা করেছি এবং সর্বশেষতম ক্রোম, এফএফ এবং ম্যাকের সাফারিতে দুর্দান্ত কাজ করেছি।

সম্পাদনা: আমি ফন্টের আকারটিও যুক্ত করেছি এবং সিস্টেম ফন্টের পরিবর্তে ওয়েবফন্টের সাথে পরীক্ষা করেছি - দুর্দান্ত কাজ করে।


7

আমি এই সমস্যাটি স্ট্রেটফোরওয়ার্ড - পিক্সেল ম্যানিপুলেশন ব্যবহার করে সমাধান করেছি।

এখানে গ্রাফিকাল উত্তর:

এখানে কোড:

    function textHeight (text, font) {

    var fontDraw = document.createElement("canvas");

    var height = 100;
    var width = 100;

    // here we expect that font size will be less canvas geometry
    fontDraw.setAttribute("height", height);
    fontDraw.setAttribute("width", width);

    var ctx = fontDraw.getContext('2d');
    // black is default
    ctx.fillRect(0, 0, width, height);
    ctx.textBaseline = 'top';
    ctx.fillStyle = 'white';
    ctx.font = font;
    ctx.fillText(text/*'Eg'*/, 0, 0);

    var pixels = ctx.getImageData(0, 0, width, height).data;

    // row numbers where we first find letter end where it ends 
    var start = -1;
    var end = -1;

    for (var row = 0; row < height; row++) {
        for (var column = 0; column < width; column++) {

            var index = (row * width + column) * 4;

            // if pixel is not white (background color)
            if (pixels[index] == 0) {
                // we havent met white (font color) pixel
                // on the row and the letters was detected
                if (column == width - 1 && start != -1) {
                    end = row;
                    row = height;
                    break;
                }
                continue;
            }
            else {
                // we find top of letter
                if (start == -1) {
                    start = row;
                }
                // ..letters body
                break;
            }

        }

    }
   /*
    document.body.appendChild(fontDraw);
    fontDraw.style.pixelLeft = 400;
    fontDraw.style.pixelTop = 400;
    fontDraw.style.position = "absolute";
   */

    return end - start;

}

2
আমি বিশ্বাস করি যে এই সমাধানটি ছোট হাতের অক্ষরগুলি I এবং J এর মতো
বিন্দুগুলিকে বিবেচনা করে না

3

আমি একটি টার্মিনাল এমুলেটর লিখছি তাই আমার অক্ষরের চারপাশে আয়তক্ষেত্র আঁকতে প্রয়োজন।

var size = 10
var lineHeight = 1.2 // CSS "line-height: normal" is between 1 and 1.2
context.font = size+'px/'+lineHeight+'em monospace'
width = context.measureText('m').width
height = size * lineHeight

স্পষ্টতই যদি আপনি চান চরিত্রটি যে পরিমাণ স্থান গ্রহণ করে তার সঠিক পরিমাণটি, এটি কোনও সাহায্য করবে না। তবে এটি আপনাকে নির্দিষ্ট ব্যবহারের জন্য একটি ভাল আনুমানিকতা দেবে।


3

আমি এইচটিএমএল ক্যানভাস ব্যবহার করে পাঠ্যের সঠিক উচ্চতা এবং প্রস্থ পরিমাপ করার জন্য একটি দুর্দান্ত গ্রন্থাগার প্রয়োগ করেছি। এটি আপনার যা করা উচিত তা করা উচিত।

https://github.com/ChrisBellew/text-measurer.js


আপনার সম্ভবত পড়া উচিত কীভাবে ব্যক্তিগত ওপেন সোর্স লাইব্রেরি অফার করবেন? আরও উত্তর আপনার গ্রন্থাগার পোস্ট করার আগে।
মার্টিজন পিটারস

3

এখানে একটি সাধারণ ফাংশন। কোনও লাইব্রেরির দরকার নেই।

বেসলাইন সম্পর্কিত উপরের এবং নীচের সীমানা পেতে আমি এই ফাংশনটি লিখেছি। যদি textBaselineসেট করা থাকে alphabetic। এটি যা করে তা হ'ল এটি অন্য ক্যানভাস তৈরি করে এবং তারপরে সেখানে আঁকবে এবং তারপরে শীর্ষ সর্বাধিক এবং নীচের সর্বাধিক খালি পিক্সেলের সন্ধান করবে। এবং এটি শীর্ষ এবং নীচে সীমা। এটি এটিকে আপেক্ষিক হিসাবে ফিরিয়ে দেয়, সুতরাং উচ্চতা যদি 20px হয় এবং বেসলাইনের নীচে কিছুই না থাকে তবে উপরের বাউন্ডটি হবে-20

আপনার অবশ্যই এটিতে অক্ষর সরবরাহ করতে হবে। অন্যথায় এটি আপনাকে 0 উচ্চতা এবং 0 প্রস্থ দেবে, স্পষ্টতই।

ব্যবহার:

alert(measureHeight('40px serif', 40, 'rg').height)

ফাংশনটি এখানে:

function measureHeight(aFont, aSize, aChars, aOptions={}) {
    // if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
    // if you dont pass in a width to aOptions, it will return it to you in the return object
    // the returned width is Math.ceil'ed
    console.error('aChars: "' + aChars + '"');
    var defaultOptions = {
        width: undefined, // if you specify a width then i wont have to use measureText to get the width
        canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
        range: 3
    };

    aOptions.range = aOptions.range || 3; // multiples the aSize by this much

    if (aChars === '') {
        // no characters, so obviously everything is 0
        return {
            relativeBot: 0,
            relativeTop: 0,
            height: 0,
            width: 0
        };
        // otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
    }

    // validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined

    var can;
    var ctx; 
    if (!aOptions.canAndCtx) {
        can = document.createElement('canvas');;
        can.mozOpaque = 'true'; // improved performanceo on firefox i guess
        ctx = can.getContext('2d');

        // can.style.position = 'absolute';
        // can.style.zIndex = 10000;
        // can.style.left = 0;
        // can.style.top = 0;
        // document.body.appendChild(can);
    } else {
        can = aOptions.canAndCtx.can;
        ctx = aOptions.canAndCtx.ctx;
    }

    var w = aOptions.width;
    if (!w) {
        ctx.textBaseline = 'alphabetic';
        ctx.textAlign = 'left'; 
        ctx.font = aFont;
        w = ctx.measureText(aChars).width;
    }

    w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number

    // must set width/height, as it wont paint outside of the bounds
    can.width = w;
    can.height = aSize * aOptions.range;

    ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
    ctx.textBaseline = 'alphabetic';
    ctx.textAlign = 'left'; 

    ctx.fillStyle = 'white';

    console.log('w:', w);

    var avgOfRange = (aOptions.range + 1) / 2;
    var yBaseline = Math.ceil(aSize * avgOfRange);
    console.log('yBaseline:', yBaseline);

    ctx.fillText(aChars, 0, yBaseline);

    var yEnd = aSize * aOptions.range;

    var data = ctx.getImageData(0, 0, w, yEnd).data;
    // console.log('data:', data)

    var botBound = -1;
    var topBound = -1;

    // measureHeightY:
    for (y=0; y<=yEnd; y++) {
        for (var x = 0; x < w; x += 1) {
            var n = 4 * (w * y + x);
            var r = data[n];
            var g = data[n + 1];
            var b = data[n + 2];
            // var a = data[n + 3];

            if (r+g+b > 0) { // non black px found
                if (topBound == -1) { 
                    topBound = y;
                }
                botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
                break;
            }
        }
    }

    return {
        relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
        relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
        height: (botBound - topBound) + 1,
        width: w// EDIT: comma has been added to fix old broken code.
    };
}

relativeBot, relativeTop এবং heightরিটার্ন অবজেক্টে দরকারী জিনিস।

এখানে উদাহরণ ব্যবহার:

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script>
function measureHeight(aFont, aSize, aChars, aOptions={}) {
	// if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
	// if you dont pass in a width to aOptions, it will return it to you in the return object
	// the returned width is Math.ceil'ed
	console.error('aChars: "' + aChars + '"');
	var defaultOptions = {
		width: undefined, // if you specify a width then i wont have to use measureText to get the width
		canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
		range: 3
	};
	
	aOptions.range = aOptions.range || 3; // multiples the aSize by this much
	
	if (aChars === '') {
		// no characters, so obviously everything is 0
		return {
			relativeBot: 0,
			relativeTop: 0,
			height: 0,
			width: 0
		};
		// otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
	}
	
	// validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined
	
	var can;
	var ctx; 
	if (!aOptions.canAndCtx) {
		can = document.createElement('canvas');;
		can.mozOpaque = 'true'; // improved performanceo on firefox i guess
		ctx = can.getContext('2d');
		
		// can.style.position = 'absolute';
		// can.style.zIndex = 10000;
		// can.style.left = 0;
		// can.style.top = 0;
		// document.body.appendChild(can);
	} else {
		can = aOptions.canAndCtx.can;
		ctx = aOptions.canAndCtx.ctx;
	}
	
	var w = aOptions.width;
	if (!w) {
		ctx.textBaseline = 'alphabetic';
		ctx.textAlign = 'left';	
		ctx.font = aFont;
		w = ctx.measureText(aChars).width;
	}
	
	w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number
	
	// must set width/height, as it wont paint outside of the bounds
	can.width = w;
	can.height = aSize * aOptions.range;
	
	ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
	ctx.textBaseline = 'alphabetic';
	ctx.textAlign = 'left';	
	
	ctx.fillStyle = 'white';
	
	console.log('w:', w);
	
	var avgOfRange = (aOptions.range + 1) / 2;
	var yBaseline = Math.ceil(aSize * avgOfRange);
	console.log('yBaseline:', yBaseline);
	
	ctx.fillText(aChars, 0, yBaseline);
	
	var yEnd = aSize * aOptions.range;
	
	var data = ctx.getImageData(0, 0, w, yEnd).data;
	// console.log('data:', data)
	
	var botBound = -1;
	var topBound = -1;
	
	// measureHeightY:
	for (y=0; y<=yEnd; y++) {
		for (var x = 0; x < w; x += 1) {
			var n = 4 * (w * y + x);
			var r = data[n];
			var g = data[n + 1];
			var b = data[n + 2];
			// var a = data[n + 3];
			
			if (r+g+b > 0) { // non black px found
				if (topBound == -1) { 
					topBound = y;
				}
				botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
				break;
			}
		}
	}
	
	return {
		relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
		relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
		height: (botBound - topBound) + 1,
		width: w
	};
}

</script>
</head>
<body style="background-color:steelblue;">
<input type="button" value="reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg', {canAndCtx:{can:document.getElementById('can'), ctx:document.getElementById('can').getContext('2d')}}).height)">
<input type="button" value="dont reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg').height)">
<canvas id="can"></canvas>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>

দ্য relativeBotএবং relativeTopআপনি এই চিত্রকে এখানে দেখতে আছেন:

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text


3

একটি লাইন উত্তর

var height = parseInt(ctx.font) * 1.2; 

সিএসএস "লাইন-উচ্চতা: স্বাভাবিক" 1 এবং 1.2 এর মধ্যে হয়

আরও তথ্যের জন্য এখানে পড়ুন


2

মজার বিষয় যে টেক্সটমেট্রিক্সের কেবল প্রস্থ এবং উচ্চতা নেই:

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#textmetrics

আপনি এই উদাহরণ হিসাবে একটি স্প্যান ব্যবহার করতে পারেন?

http://mudcu.be/journal/2011/01/html5-typographic-metrics/#alignFix


1
শুধুমাত্র প্রস্থ থাকার কারণটি হ'ল: stackoverflow.com/a/12112978/1085483
রুই মার্কস

2

আমি এখানে অন্যান্য উত্তরগুলির উপর ভিত্তি করে এটি করেছি:

function measureText(text, font) {
	const span = document.createElement('span');
	span.appendChild(document.createTextNode(text));
	Object.assign(span.style, {
		font: font,
		margin: '0',
		padding: '0',
		border: '0',
		whiteSpace: 'nowrap'
	});
	document.body.appendChild(span);
	const {width, height} = span.getBoundingClientRect();
	span.remove();
	return {width, height};
}

var font = "italic 100px Georgia";
var text = "abc this is a test";
console.log(measureText(text, font));


1

প্রথমত, আপনাকে একটি ফন্টের আকারের উচ্চতা নির্ধারণ করতে হবে এবং তারপরে আপনার পাঠ্যের বর্তমান উচ্চতা নির্ধারণ করতে হরফের উচ্চতার মান অনুযায়ী কতগুলি, ক্রস-পাঠ্য রেখাগুলি, অবশ্যই একই উচ্চতা হবে হরফটি জমা করতে হবে, যদি পাঠ্যটি বৃহত্তম পাঠ্য বাক্স উচ্চতা অতিক্রম না করে, সমস্ত প্রদর্শন করুন, অন্যথায়, কেবল বাক্সের পাঠ্যের মধ্যেই পাঠ্যটি দেখান। উচ্চ মানের আপনার নিজস্ব সংজ্ঞা প্রয়োজন। প্রিসেটের উচ্চতা যত বেশি হবে, পাঠ্যের উচ্চতা যত বেশি প্রদর্শিত হবে এবং বাধা দেওয়া দরকার।

প্রভাব প্রক্রিয়া করার পরে (সমাধান)

প্রভাবটি প্রক্রিয়া করার আগে (অমীমাংসিত)

  AutoWrappedText.auto_wrap = function(ctx, text, maxWidth, maxHeight) {
var words = text.split("");
var lines = [];
var currentLine = words[0];

var total_height = 0;
for (var i = 1; i < words.length; i++) {
    var word = words[i];
    var width = ctx.measureText(currentLine + word).width;
    if (width < maxWidth) {
        currentLine += word;
    } else {
        lines.push(currentLine);
        currentLine = word;
        // TODO dynamically get font size
        total_height += 25;

        if (total_height >= maxHeight) {
          break
        }
    }
}
if (total_height + 25 < maxHeight) {
  lines.push(currentLine);
} else {
  lines[lines.length - 1] += "…";
}
return lines;};

1

আমি দেখতে পেলাম যে জাস্ট ফর এরিয়ালের জন্য সীমাবদ্ধ বাক্সের উচ্চতা নির্ধারণের সহজতম, দ্রুত এবং নির্ভুল উপায় হ'ল নির্দিষ্ট বর্ণগুলির প্রস্থ ব্যবহার করা। আপনি যদি ব্যবহারকারীকে আলাদা আলাদা আলাদা পছন্দ না করে কোনও নির্দিষ্ট ফন্ট ব্যবহার করার পরিকল্পনা করেন তবে আপনি সেই ফন্টের জন্য কাজ করে এমন সঠিক চিঠিটি খুঁজে পেতে একটু গবেষণা করতে পারেন।

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="700" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "100px Arial";
var txt = "Hello guys!"
var Hsup=ctx.measureText("H").width;
var Hbox=ctx.measureText("W").width;
var W=ctx.measureText(txt).width;
var W2=ctx.measureText(txt.substr(0, 9)).width;

ctx.fillText(txt, 10, 100);
ctx.rect(10,100, W, -Hsup);
ctx.rect(10,100+Hbox-Hsup, W2, -Hbox);
ctx.stroke();
</script>

<p><strong>Note:</strong> The canvas tag is not supported in Internet 
Explorer 8 and earlier versions.</p>

</body>
</html>


0

হরফ আকার নির্ধারণ করা যদিও ব্যবহারিক হতে পারে না, সেট করার পরে

ctx.font = ''

সিএসএস দ্বারা নির্ধারিত একটি পাশাপাশি কোনও এম্বেড থাকা ফন্ট ট্যাগ ব্যবহার করবে। আপনি যদি সিএসএস হরফ ব্যবহার করেন তবে মাপের পাঠ্য পদ্ধতিটি যা খুব স্বল্প দৃষ্টিশক্তি ব্যবহার করে কোনও প্রোগ্রামিক পদ্ধতিতে উচ্চতা কী তা আপনার কোনও ধারণা নেই। যদিও অন্য একটি নোটে, IE8 প্রস্থ এবং উচ্চতা ফিরে আসে।


0

এটি 1) মাল্টলাইন পাঠ্যের পাশাপাশি 2) এমনকি আই 9 তেও কাজ করে!

<div class="measureText" id="measureText">
</div>


.measureText {
  margin: 0;
  padding: 0;
  border: 0;
  font-family: Arial;
  position: fixed;
  visibility: hidden;
  height: auto;
  width: auto;
  white-space: pre-wrap;
  line-height: 100%;
}

function getTextFieldMeasure(fontSize, value) {
    const div = document.getElementById("measureText");

    // returns wrong result for multiline text with last line empty
    let arr = value.split('\n');
    if (arr[arr.length-1].length == 0) {
        value += '.';
    }

    div.innerText = value;
    div.style['font-size']= fontSize + "px";
    let rect = div.getBoundingClientRect();

    return {width: rect.width, height: rect.height};
};

0

আমি জানি এটি একটি পুরানো উত্তরযুক্ত প্রশ্ন, তবে ভবিষ্যতের রেফারেন্সের জন্য আমি একটি সংক্ষিপ্ত, ন্যূনতম, জেএস-কেবল (কোনও জেকারি নয়) সমাধান যুক্ত করতে চাই যে আমি বিশ্বাস করি লোকেরা এতে উপকৃত হতে পারে:

var measureTextHeight = function(fontFamily, fontSize) 
{
    var text = document.createElement('span');
    text.style.fontFamily = fontFamily;
    text.style.fontSize = fontSize + "px";
    text.textContent = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
    document.body.appendChild(text);
    var result = text.getBoundingClientRect().height;
    document.body.removeChild(text);
    return result;
};

-3

সাধারণ পরিস্থিতিতে নিম্নলিখিতগুলি কাজ করা উচিত:

var can = CanvasElement.getContext('2d');          //get context
var lineHeight = /[0-9]+(?=pt|px)/.exec(can.font); //get height from font variable

5
সম্পূর্ণ এবং সম্পূর্ণ ভুল। পয়েন্ট আকার এবং একটি পিক্সেল আকারের মধ্যে একটি বিশাল পার্থক্য রয়েছে। পৃষ্ঠার যে ডিপআইটি রেন্ডার করা হচ্ছে তার উপর নির্ভর করে বিভিন্ন আকারের পাঠ্যে বিন্দু আকারের ফলাফল ফলাফল যেখানে পিক্সেল আকার হিসাবে তা বিবেচনায় নেয় না।
অরভিড কিং

2
আপনি কি স্ক্রিন পিক্সেল ধারণার সাথে পরিচিত? আপনি এটি আলোকিত করতে পারেন। নির্বিশেষে, pt এবং px প্রকৃতপক্ষে বিভিন্ন উচ্চতা নির্দেশ করে। এটি লক্ষ্য করার মতো যে হরফটি এটি "উচ্চতা" এর চেয়ে কম বা আরও যাইহোক পূরণ করতে পারে। আমি নিশ্চিত নন যে ক্যানভাস পিক্সেলগুলি ছোট করা হয়েছে, তবে আমি অনুমান করি। যদিও এটি একটি "ভুল" উত্তর। এটি সহজ এবং অনেক পরিস্থিতিতে ব্যবহার করা যেতে পারে।
লোডেভিজক

-4

এটি ম্যাডিং করছে ... পাঠ্যের উচ্চতা হরফ আকার ... আপনারা কেউ ডকুমেন্টেশন পড়েন নি?

context.font = "22px arial";

এটি উচ্চতা 22px এ সেট করবে।

একমাত্র কারণ আছে ..

context.measureText(string).width

কারণ স্ট্রিংটির প্রস্থ নির্ধারণ করা যায় না যদি না আপনি স্ট্রিংটি জানেন যে আপনি প্রস্থটি চান তবে ফন্টের সাহায্যে আঁকা সমস্ত স্ট্রিংয়ের জন্য ... উচ্চতা 22px হবে।

আপনি যদি px এর চেয়ে অন্য কোনও পরিমাপ ব্যবহার করেন তবে উচ্চতা এখনও একই থাকবে তবে সেই পরিমাপের সাথে তাই আপনাকে যতটা করতে হবে তা পরিমাপকে রূপান্তরিত করতে হবে।


কিছু অক্ষর সীমা ছাড়িয়ে উপরে বা নীচে প্রসারিত হতে পারে, দেখুন wwg.org/specs/web-apps/current-work/images/baselines.png
অষ্টাভিয়া তোগামি

1
খারাপভাবে শব্দযুক্ত কিন্তু এখনও সত্য।
লোডেভিজক

এই সব উত্তর পড়ুন কিন্তু আমার সহজ অ্যাপ্লিকেশন জন্য এটি কি সঠিক উত্তর, পর্তুগীজ ভাষায় === px আকারে ছিল
ডাকাতি

পুরোপুরি ভুল। বিভিন্ন ফন্টের সাথে প্রস্তাবিত কিছু সমাধান চেষ্টা করে দেখুন এবং আপনি বড় ধরনের ত্রুটি খুঁজে পাবেন।
ডেল অ্যান্ডারসন

-4

আনুমানিক সমাধান:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "100px Arial";
var txt = "Hello guys!"
var wt = ctx.measureText(txt).width;
var height = wt / txt.length;

এটি মনোস্পিডযুক্ত ফন্টের সঠিক ফলাফল হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.