entry = () =>{
const obj = doc.body;
const css = doc.createElement("style");
css.type = "text/css";
css.innerHTML = Fid("emoCssDisp").textContent;
doc.body.append(css);
doc.body.classList.add("ent");
doc.body.classList.add("emo-entry");
const par = Fid("flagPar");
let s = par.innerHTML.replace(/([\ud800-\udfff]{4})/g,
`\x3cspan onclick="flagSec(this)">$1\x3c/span>`);
par.innerHTML = s;
flagSec(Ftag("flagPar","span")[1]);
Fid("ccPar").innerHTML = `\x3ctextarea id="flagCc">\x3c/textarea>`;
flagEntry(1);
cfSec(1);
};
flagSec = e => {
const s = e.textContent, s1 = s.substring(0,2), s2 = s.substring(2,4);
const ofs = 0x1f1e6 - 0x41;
const cc = String.fromCharCode(s.codePointAt(0)- ofs, s.codePointAt(2) - ofs);
Fid("flagInfo").innerHTML = `\x3cb>${s}\x3c/b> ISO 3166-1 : ${cc}
${s1} \x26amp;#x${cpa(s1,2)}; \\u${cpa(s1,0)}\\u${cpa(s1,1)}
${s2} \x26amp;#x${cpa(s2,2)}; \\u${cpa(s2,0)}\\u${cpa(s2,1)}
${s} : \x26amp;#x${cpa(s1,2)};\x26amp;#x${cpa(s2,2)};`.
replace(/\n/g, "\x3cbr>");
};
cfSecEntry = e => {
alert(e.title);
};
cfSec = no => {
const disp = Fid("cfDisp");
disp.classList.remove("cl");
if(no == 0){
disp.innerHTML = "";
return;
}
const dat = Fid("flagCc").value.match(/[A-Z]{2}/g);
const st = 0x1f1e6;
let s = "";
for(let o of dat){
let s1 = st + o.charCodeAt(0) - 0x41;
let s2 = st + o.charCodeAt(1) - 0x41;
s += `\x3cspan title="${o}" onclick="cfSecEntry(this)">\x26#${s1};\x26#${s2};\x3c/span> `;
}
disp.innerHTML = s;
disp.classList.add("cl");
};
/* 領域に国旗を生成する
cn:国コード、空白、カンマ区切り
par:送り先
add:1:追加 0:上書き
func:イベント
*/
createSpan = (cn, par, add, func) => {
let s = "";
const cc = (o,n) => "\x26#" + (0x1f1e6 + o.charCodeAt(n)- 0x41) + ";";
const dat = cn.match(/[A-Z]{2}/g);
for(let dt of dat){
let fn = func != "" ? ` onclick="${func}(this)"` : "";
s += `\x3cspan${fn} title="${dt}">${cc(dt,0)}${cc(dt,1)}\x3c/span> `;
}
const obj = Fid(par);
add ? obj.innerHTML += s : obj.innerHTML = s;
};
flagEntry = no => {
const par = Fid("axDisp");
if(flagEntry.buf == null) flagEntry.buf = par.innerHTML;
if(no == 2){
par.innerHTML = flagEntry.buf;
return;
}
const st = 0x1f1e6;
let i,j,obj,s = "", sum = "";
let len = 0;
for(i = 0; i != 26; i++){
for(j = 0; j != 26; j++){
obj = String.fromCharCode(0x41 + i, 0x41 + j);
s += `\x3cspan class="flag" title="${obj}">\x26#${st + i};\x26#${st + j};\x3c/span>`;
}
}
par.innerHTML = `\x3cdiv id="sumDisp">\x3c/div>\x3cdiv id="flags">${s}\x3c/div>`;
if(no){
obj = Ftag(par, "span");
const d1 = obj[0].offsetWidth;
for(i = 0; i != obj.length; i++){
if(obj[i].offsetWidth == d1){
obj[i].classList.add(no == 1 ? "no" : "hide");
} else {
len++;
sum += obj[i].title + " ";
}
}
Fid("flagCc").value = sum;
Fid("ccParCnt").textContent = len;
}
};
cpa = (s, n) => (n == 2 ? s.codePointAt(0) : s.charCodeAt(n)).toString(16);
entry();
body.ent div.hide {
display:block;
}
#emoPia.loaded .emo {
font-size:1rem;
transform:scale(1);
}
.e1, span.w2{
font-size:1.6rem;
color:tomato;
letter-spacing:5px;
display:inline-block;
text-shadow:0 0 2px #000, 2px 2px 2px #666;
}
.e1::first-letter {
color:magenta;
}
a.fix {
display:inline-block;
text-decoration:underline dotted 3px;
float:right;
}
a:hover {
color:magenta;
}
#flagPar {
letter-spacing:0;
padding:.75rem 1rem;
}
.emo-entry a.ent-link {
font-size:0px;
}
.emo-entry #flagPar span {
}
#flagPar span:hover {
background-color:#ff3;
}
#flagDisp span {
display:inline-block;
font-size:2.7em;
line-height:1em;
margin-right:.25rem;
}
#flagCc {
display:block;
width:100%;
padding-left:2px;
padding-right:2px;
border:2px solid #808080;
border-radius:6px;
background-color:#ffefff;
height:12.6em;
line-height:1.4;
scroll-behavior:smooth;
transition:height .4s;
}
.cf-disp {
width:100%;
font-family:monospace;
font-size:0px;
line-height:0px;
border:1px solid #ccc;
border-radius:6px;
box-shadow:3px 3px 3px #ccc;
padding:.5rem;
transiton:all .5s;
}
#cfDisp, #axDisp {
background-color:#eef;
height:22rem;
overflow:auto;
}
.cf-disp span {
display:inline-block;
font-size:3rem;
line-height:3rem;
cursor:pointer;
padding:0 .25rem;
opacity:0;
transition:background-color .3s, opacity .5s;
}
.cf-disp.cl span {
opacity:1;
}
.cf-disp span:hover {
background-color:#ff3;
}
国旗が文字で綴れるって素敵なことだと思います。
しかも、連結文字の仕様もセンスが溢れています。
🇯🇵🇺🇸🇰🇷🇨🇳🇰🇵
🇩🇪🇳🇴🇨🇦🇬🇧🇦🇺
🇦🇨🇧🇲🇨🇰🇫🇯🇫🇰
🇹🇻🇮🇪🇲🇫🇨🇮🇹🇩
🇦🇩🇮🇨🇹🇫🇼🇫🇹🇷
位置合わせの工夫
・letter-spacing: 1rem → 0
・.75rem .5rem .75rem 1.5rem
→ .75rem 1rem (padding)
・flags span padding: 0 .5rem
💙絵文字の考察 ~国旗~
上の国旗は画像じゃなくて文字です。それらは(🇺🇸)みたいに小さいから親の要素のCSSで拡大しています。通常の漢字や
❤ は2バイトになるし、💙💛💗などは4バイトになるのですけれど国旗は連結文字で8バイトになるの。🇯と🇵で🇯🇵になるし、🇺と🇸で🇺🇸になるわ。
その国旗の連結の文字は🇦から🇿の26字です。uniCodeでは
U+1F1E6 - U+1F1FF になるのですが、中途半端な開始位置は領域割り当てでブロックの最後に合わせた感じがします。連番だから便利ですよね。連結文字から国コードを求めるのも簡単にできそうです。
💙国旗からの国コードの抽出
・ofs = 0x1f1e6 - 0x41;
・s = /([\ud83c][\udde6-\uddff]){4}/g または /([\u{1f1e6}-\u{1f1ff}]){2}/g
・cc = String.fromCharCode(s.codePointAt(0)- ofs, s.codePointAt(2) - ofs);
💙U+1F1(E6-FF)の総当たりで国旗の求め方
・0-25の2重ループ
・オフセット:st = 0x1f1e6
・国コード:String.fromCharCode(0x41 + i, 0x41 + j)
・連結文字:\x26#${st + i};\x26#${st + j}
・連結して国旗になる場合は
offsetWidthが変化
・国コード一覧の生成:現在258の国々
→ もしも下のリストの個数に変化があれば情勢がが変化しています。
#ccPar 有効な国コード抽出結果:
0
💙全ての国々のコードが求められたなら総当たりのルーブを通す必要がないわ。こんどはそのリストから下の領域に国旗を表示してみます。タグ入れしてイベントを付けました。リストは抽出されたものだから単に
match(/[A-Z]{2}/g )で
for ofを回せばいいわね。
💗
登録された全ての国旗を表示 |
白紙にする
そのまま | ABは小さく | ABは非表示 | 元の状態に戻す
🇦🇷🇦🇺🇯🇵🇦🇧🇺🇸🇵🇷
🇦から🇿の総組み合わせが上で分かると思います。2文字ずつ
spanに入れていますから全て表示された後に、それぞれの
offsetWidthを比較すれば国旗として認識したかどうかが分かります。その有効な組み合わせを纏めたものが少し前の
ccPar配下にあるテキスト領域です。ひとたび国コードのリストが生成されれば上のリストは必要ないのですが、新たな国が増えないとは限りないし、処理の参考の為に残すことにします。
💙国旗の間隔と改行のこと。
・🇦🇷🇦🇺🇺🇸🇵🇷 文字としてはこんな感じです。小さくて左右ぴったりです。
・
🇦🇷🇦🇺🇺🇸🇵🇷 font-size:3rem; line-height:3rem;
・文字を大きくすると行送りも広がるのでそれも指定。でも文字間隔がダメです。
・
🇦🇷🇦🇺🇺🇸🇵🇷 font-size:3rem; line-height:3rem; letter-spacing:.5rem;
・普通は国旗が連続しているとき空白が無い場合は改行されません。
・spanの中に入れてfont-size:3rem、親にfont-size:0 を入れ、直後に空白を入れています。親サイズはゼロだからspanの余白で文字間隔を合わせています。
💙関数の実装 :
テスト
{
let o = document.createElement("script");
o.id = "bootScript";
o.src = "http://nancyan.main.jp/html5/eclat/new-diary/diary_boot.js?emoPin";
o.charset = "utf-8";
o.type = "text/javascript";
document.head.append(o);
}