dポイントプレゼントキャンペーン実施中!

タグ要素から文字がはみ出た時に文字サイズを小さくする処理をしようとしている途中なのですが、
「」は簡略で書くと

親のfor文からネストして

for(j=0;「テキストの幅」 < getContentWidth(「要素の幅」) ||「文字サイズが23px」 ; j++){
/* 文字を小さくしすぎたので調整でフォントサイズを1pxずつ大きくする*/
size [j] +=1;
}

getContentWidth()は任意の関数で以下のようにしました。

//要素のWidthからpaddingを引いてコンテンツの幅を出してreturn
function getContentWidth (elem) {
var styles = window.getComputedStyle(elem);
return elem.clientWidth
- parseFloat(styles.paddingLeft)
- parseFloat(styles.paddingRight)
}

デバッグで、「要素の幅」は約48px < getContentWidth()の戻り値は179pxで「文字サイズ」は20pxなのですが、子のfor文に入らず、親のfor文に戻ります。

****以下原文貼り付け*****(テキストエディタ等に貼ってみてください)
var elements = document.getElementsByTagName('address');
//elements[0]だけなのは、addressタグは1つだけだから
var element = elements[0].children;//address[0]=addressタグは1つ。の直下のタグ要素を取得
var text = element.textContent;//タグ要素のcontentのテキストを取得
const ctx = document.createElement('canvas').getContext('2d');//特殊なデータ加工用の変数を用意する
var textWidth=ctx.measureText(text).width;//contentのテキストのwidthを取得
var size = new Array();//配列を用意して初期化する
let i,j;
function resize() {
for (i=j= 0 , size[i]=23; i < element.length; i++) {
if (
//clientWidth(Height)は、margin/border/scroll幅は含まず、paddingを含む
element[i].clientHeight < element[i].scrollHeight && size[i] > 9 ||
element[i].clientWidth < element[i].scrollWidth && size[i] > 9){
for (
j=0;
element[i].clientHeight < element[i].scrollHeight && size[j] > 9 ||
element[i].clientWidth < element[i].scrollWidth && size[j] > 9 ;
j++){
/* 文字がはみ出すサイズが存在していたので、フォントサイズを3pxずつ小さくする*/
size[j]-=3;
}
for(j=0;textWidth[i] < getContentWidth(element[i]) || size[j] == 23 ; j++){
/* 文字を小さくしすぎたので調整でフォントサイズを1pxずつ大きくする*/
size[j]+=1;
element[i].style.fontSize = size[j] + "px";
}
}else{
for (j=0;textWidth[i] < getContentWidth(element[i]);j++) {
/* 実コンテンツが要素の幅より小さいときは1pxずつフォントサイズを大きくする*/
size [j] +=1;
element[i].style.fontSize = size[j] + "px";
}
}
}
}
//ブラウザを開いたとき
window.onload = function(){
resize();
}

//ウインドウサイズを変えたとき
window.addEventListener('resize', () => {
resize();
})
//コンテンツのWidthを取得する
function getContentWidth (elem) {
var styles = window.getComputedStyle(elem);
return elem.clientWidth
- parseFloat(styles.paddingLeft)
- parseFloat(styles.paddingRight)
}

/*覚え書き用ー処理に関係なし*/
//getComputedStyle(elem).width{height}はCSSで指定した要素の幅(マージン・ボーダー・パディング含まない)で、レンダリングされたらその値を示す。

A 回答 (4件)

No3です。



>アドレスタグの子要素が配列で取得されるため、
>配列の取得に合わせてフォントサイズ用の配列を用意して~
その子要素には子孫要素は存在せず、子要素内ではフォントは全て一律だという前提条件があるのでしょうか?
仮にそうだとしても、(No3でも指摘しましたが)以下のようなHTMLは対象外ということで良いのですね?

<address>
◇ 連絡先 ◇<br>
URL:<a href="~~">//hoge.com<a><br>
E-mail:<a href="~~">fuga@fuga</a><br>
折り返しがあるような長い文字列 (---省略---)
</address>

もしそうだとするなら、対象としているHTML構造はかなり限定的な特徴のあるものと思いますので、それ専用にスクリプトを作成する方が簡単だと思います。
いずれにしろ、完全に汎用的なものを作成しようとするとかなり面倒だと思いますので、ある程度の構造の想定やCSSの制限は必要とは思いますけれど・・


>>size[j]-=3;
>などは計算できない可能性が大と考えられますけれど・・?
>→どうすればいいのでしょうか?
四則演算をしたいのであれば、初期値を数値として設定しておく必要があると思われます。
No3でも示しましたように、ご提示のスクリプトではほとんどの値がundefinedのままですので、数値計算をしようとしてもNaNになるだけと想像します。
四則演算だけでなく、if文の条件判定も(多分)意図とは違う結果になると思います。
(undefined > 9 等は false となると思いますので、常に、偽判定となるでしょう)

※ ついでながら、No3の回答での配列の内容は誤りでしたね。失礼いたしました。
 正しくは [23, undefined, indefined, ・・・] となるものと思います。
    • good
    • 0

こんにちは



申し訳ありませんけれど、あまりきちんと読む気がしないスクリプトなので、最初の方を拾い読みしただけですが・・
どのような要素構成までを対象にしようとしているのかも不明なので、何ともわかりかねますが、いろいろと勘違い(?)があるように思われます。

>var textWidth=ctx.measureText(text).width;
キャンバス上の文字列のサイズ(幅)を取得しようとしているようですが、実際にレイアウトされている要素(=文字列)の幅と同じになるという保証はないと思われます。
文字列の幅はfont-sizeだけでなく、種類(font-family)や太さ、斜体等によってもいろいろと変わってきますので・・
また、子要素を想定しているようですが、textContentだけでの比較では、子要素のmarginやpaddingなどに関しては無視していることになります。

そもそもになりますが
>var text = element.textContent;
elementは elements[0].children ですので要素リストのはずです。
いきなり textContent を得ようとしても、この時点でundefinedになっていませんか?
仮に、取得できるとしても、複数の要素を包含している場合には、レイアウト等を考慮する必要がありそうに思われますけれど・・
(例えば、<br>を含んでいる場合など・・)

それ以降は何をしようとしているのか、さっぱりわかりませんけれど、ご質問文で問題視なさっているfor文については、配列size[] の意味がわかりかねます。
sizeの内容は [0, undefined, indefined, ・・・] となりますけれど、これは意図通りなのでしょうか?
その後に記されている、
>size[j]-=3;
などは計算できない可能性が大と考えられますけれど・・?

例えば、ご提示の一部を簡略化して抜き出してみて、
 let i, j, size = new Array();
 for (i=j= 0 , size[i]=23; i < 10; i++) {
  alert( `size[${i}]= ${size[i]}`);
 }
とでもして実行してみれば、おわかりになるかと。


話は変わりますが・・
>要素から文字がはみ出た時に文字サイズを小さくする処理をしようとしている
対象をどこまで汎用化してお考えなのか不明ですが、少なくとも上記のように文字サイズだけを変えることで幅を計算しようというところに無理がありそうに思われます。
また、address要素内に直接のテキストノードがあったり、<br>での改行があったりする場合にどうするのかなどなど、最初に処理のロジックとして考慮しておくべき点が多々ありそうに思われます。

ごく大雑把に考えるなら、現状の内容を white-space: nowrap;で表示した際の幅と現状の幅の比を求めて、これを現状の文字サイズに乗ずることで、ほぼピッタリのサイズを計算可能と思いますが・・
対象内の文字サイズがいろいろ混在している可能性がある場合も考慮するのなら、そのまま全体をtransformで縮小/拡大してしまった方が簡単なのかも知れません。

一方で、要素幅をclientWidth で計算しているようですけれど、当該要素が transform: scale() などで倍率指定されている場合は、レンダリングされた実際の幅を取得できないなどの問題もあるかも知れませんけれど・・


※ 実際に処理しようとしている対象の内容や条件設定等が不明なので、ひとまずはこの辺で・・
    • good
    • 0
この回答へのお礼

ありがとう

詳しく、回答いただき、ありがとうございます。
初心者の為、意味不明なコーディングご容赦ください。
アドバイスくださった所、為になります。そもそも論で問題だらけなのは、理解しました。手を煩わせしまうので、できたらで結構ですが、できれば今後の勉強の為にお聞きしたいしたいのですが、


>elementは elements[0].children ですので要素リストのはずです。
いきなり textContent を得ようとしても、この時点でundefinedになっていませんか?→なってました。繰り返し処理内に移動してみます。

>配列size[] の意味がわかりかねます。
→アドレスタグの子要素が配列で取得されるため、配列の取得に合わせてフォントサイズ用の配列を用意して、フォントサイズを小さくするために、繰り返し処理用の変数jを用意しています。

>size[j]-=3;
などは計算できない可能性が大と考えられますけれど・・?
→どうすればいいのでしょうか?

色々と意味不明だと思われますが、よろしくお願いします。

お礼日時:2023/11/12 16:39

まずはコーディングする際に適切なタブ付 then elseやforループを見やすくすると簡単なミスを見つけやすくなります。


前部行の先頭から書かれてるとプログラムの構造が見えて来ない・・・。(;_;)
正直、読むのを途中で諦めました。(_ _)

その上で。
forループで使うループカウント変数と異なる変数をループの条件式で使っている場合、その変数がきちんとループ内でインクリメント、デクリメントされているかどうかといった辺りも確認点かと思います。

参考まで。
    • good
    • 0

どこか間違えているのだと思います。



デバッグツールもあると思うので探してみてください。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A