20200305のCSSに関する記事は5件です。

Javascriptでいろいろな正星型図形(n芒星)を生成する

仕組み

図形生成の仕組みは、こちらのページの技術を応用したもの + 高校で習った三角関数。
そもそも六芒星をはじめとする星型図形にはどれだけ複雑なものであっても、線の本数と傾きは正多角形の時と変わらないという法則がある。つまり、線の傾きと位置さえ調整してやれば、煩雑な多角形であっても生成可能なのである。
で、その線の位置と長さを求めるときに使うのが、いわゆるsin、cos、tanなのだ。

図にするとこんな感じ。
1583417842156.jpg

赤線の部分がいわゆる「斜辺」と呼ばれるもの。斜辺の長さは50%=0.5で、赤線と赤線の間の角(中心角)は今回の場合5等分(赤い点=円の中心から接線に向けて伸びる直線、つまり半径なのだ)。これにsinやcosをかけてやれば値がwidthとheightの長さが求まるという寸法だ。

高校を卒業したての人に向けて言えば、「width=弦の長さ」。と言えばイメージしやすいのではないだろうか。
ちなみに、sin、cos、tanは角度をもとに線の長さを求める式である。

作例例

1583418314284.jpg
オーソドックスな六芒星。

1583416971266.jpg
第三引数(intersection)を0にすれば通常の正多角形も作図できる。

1583418677837.jpg
同じ7角形だが、第三引数を2にしてある。

1583417002963.jpg
こんな複雑なのも可能。ちなみに、400角形で頂点を188個飛ばしにつないでいる。

1583418439057.jpg
1024角形。邪神アバター呼ばわりされた。

ちなみに、星型多角形は頂点の数が増えてゆくごとに、作れる"星"の種類も増えてゆく。
最大数は(頂点数÷2)-1 以下の数。たとえば、7角形なら、7÷2=3.5、3.5-1=2.5なので、2つ作れることになる。

コード本体

html
<style>
/* position:relative、position:absolute、position:fixedのいずれか+タテヨコの高さが決まっていないと崩れるので注意。 */
#torirobyte{
    position: relative;
    width: 600px;
    height: 600px;
}   
/* border-bottomで線を表現しているので、線の太さや色はここをいじれば制御できる。 */
#torirobyte div{
    border-bottom: 1px solid black;
}
</style>


<div id="torirobyte">
</div>

<script type="text/javascript">
(function(){

var target = document.getElementById('torirobyte');
CreateGrams(target, 12, 3);

function CreateGrams(parantelm, vertex, intersection){
    // vertexは頂点数。
    // intersectionは点と点をつなぐ直線が何個飛ばしに線を作るか。0の場合、普通の正多角形ができあがります。
    // elementの中に整形されます。

    // 図形のパラメーターの設定
    var radius = 50; // 半径(widthとheightはパーセント指定するので一律50)
    var slope_per_one = 360 / vertex; // 線の傾き
    var center_angle = slope_per_one * (intersection + 1); // 中心角。この値によって、完成する星型図形が変化します。
    var radian_slope = ((180 - center_angle) / 2) * (Math.PI / 180); // sin、cosに使う角(ラジアン単位)
    var width_rate = Math.cos(radian_slope) * radius * 2; // 線に設定するwidth(単位は%)
    var height_rate = Math.sin(radian_slope) * radius * 2; // 線に設定するheight(単位は%)
    var leftposision = (100 - width_rate) / 2; // positionのleftに付ける値。これで横位置を要素内におさめる

    // 図形の生成
    parantelm.innerHTML = '';
    for(var int = 0; int < vertex; int++){
        var childs = document.createElement('div');

        // 図形逆向き化防止
        if(intersection % 2 == 0){
            var slope_current = (slope_per_one * int);
        }else{
            var slope_current = (180 + (slope_per_one * int));
        }

        childs.style.margin = 'auto';
        childs.style.position = 'absolute';
        childs.style.top = 0;
        childs.style.bottom = 0;
        childs.style.left = leftposision + '%';
        childs.style.transform = 'rotate(' + slope_current + 'deg)';
        childs.style.width = width_rate + '%';
        childs.style.height = height_rate + '%';
        parantelm.appendChild(childs);
    }
    return parantelm;
}

})();
</script>

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Bootstrap】アコーディオンが1つの時にレイアウトが崩れた話

概要

DjangoでWebアプリケーションを作成中、フロントのCSSはBootstrapを使ってデザインしていた。

viewから渡されたリストをループで処理しながらアコーディオンを作成しようとしたら、
リストが1件の時の表示がおかしくなってしまった。

ループが2件以上の時(正常):
スクリーンショット 2020-03-05 22.31.03.png

1件の時(下線切れてるし角が丸くない):
スクリーンショット 2020-03-05 22.32.04.png

ソース:

test.html
<div class="accordion" id="accordion" role="tablist" aria-multiselectable="true">
    {% for l in list %}
    <div class="card">
        <div class="card-header" role="tab" id="heading{{ forloop.counter }}">
            <h5 class="mb-0">
                <a class="text-body d-block p-3 m-n3" data-toggle="collapse" href="#collapse{{ forloop.counter }}" role="button" aria-expanded="true" aria-controls="collapse{{ forloop.counter }}">
                    {{ forloop.counter }}
                </a>
            </h5>
        </div>
        <div id="collapse{{ forloop.counter }}" class="collapse" role="tabpanel" aria-labelledby="heading{{ forloop.counter }}" data-parent="#accordion">
            <div class="card-body">
                {{ l }}
            </div>
        </div>
    </div>
    {% endfor %}
</div>

今のところの対処法

リストが1件しかない場合の分岐処理を追加し、CSSのクラスを追加してあげる。

card
<div class="card">

↑に

card-border-rounded
<div class="card {% if list|length == 1 %}border rounded{% endif %}">

↑という分岐を追加してあげると1件でも綺麗に表示してくれる。

スクリーンショット 2020-03-05 22.39.47.png

おわりに

これ解決するのに1〜2時間かけた気がする...

Djangoじゃなくてもリストのサイズがわかれば他の言語/フレームワークでもできると思うし、なんならもっといい方法がある気がする。

誰かBootstrap/CSSに詳しい人いたらもっとスマートな方法教えてください...(涙目)

ちなみにBootstrap公式ドキュメントにあるソースのアイテム2と3を全部消してアイテム1だけ残しても同じ現象が起きるから、アコーディオンが1個だけなんて使い方は想定してないんじゃないかなぁ...と勝手に思ったり。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSS

セレクタ

セレクタの構造は、セレクタ/プロパティ/値からなっている。
基本の形はセレクタ { プロパティ: 値; }となり、セレクタ構造を示すために{}を、
プロパティの値を指定する場合は、 :(コロン)を使い、値の最後には;(セミコロン)を書く。

p {
  color: black;
}

class属性

HTML要素に対して個別に名前を付けることができる機能。
例えば、<p>...</p>に対して"message"というclass名を付与する場合は、以下のように記載。

<p class="message">
  aaa
</p>

classセレクタ

HTMLで指定したclass名をセレクタとして使用することができる。
classセレクタを指定する場合は、.クラス名のような形で指定。

.message {
  color: black;
}

id属性

class属性同様に、HTML要素に対して個別に名前を付けることができる機能。
例えば、<p>...</p>に対して"message"というid名を付与する場合は、以下のように記載。

<p id="message">
  aaa
</p>

idセレクタ

HTMLで指定したid名をセレクタとして使用することができる。
idセレクタを指定する場合は、#id名のような形で指定。

#message {
  color: red;
}

classとidの使いどころの違い

class
同じclass名のものを複数回使用できる
一般的なセレクタとして使用できる

id
同じid名のものは複数回使用できない
ある特徴的な部分など、ここぞというタイミングで使用するセレクタ

コメントアウト

プログラムの中に、「メモ」を埋め込むための機能。
コメントアウトされた文字列は、コードとしては認識されない。

リセットCSS

インターネットを閲覧するためのブラウザにはいくつかの種類があるが、それぞれ独自のCSSをデフォルトで持っている。つまり、同じ<h1>...</h1>で指定しても、ブラウザごとに文字の大きさが異なったり上下の幅が異なったりする。
何らかのトラブルで、Webページ作成者が用意したCSSファイルが読み込まれなかった時、
ブラウザ側で最低限の見た目を保障するために、各ブラウザが独自のデフォルトCSSを持っている。
しかし、これが時に、Webページ作成者が用意したCSSファイルと影響しあって見た目を崩してしまうことがある。
これを防ぐため通常、各ブラウザが用意しているデフォルトのCSSを上書きするCSSを書いておく。

body {
  background-color: #f0f0f0;
  font-size: 14px;
  color: #333;
  margin: 0 auto;
}
h1,h2,h3,h4,h5,h6,p {
  padding: 10px 0;
  margin: 0;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リストなどのアイテムが無い時に「ありません」を表示させる

頭にアイテムの無い時の状態を入れておいて、アイテムが追加されたらその表示だけにする。

html
<ul>
  <li>ありません</li>
  <li>アイテム1</li>
  <li>アイテム2</li>
  <li>アイテム3</li>
</li>
css
ul > li:first-child() {
  display: none;
}
ul > li:last-child() {
  display: inherit;
}

アイテム1,2,3があれば、

  • アイテム1
  • アイテム2
  • アイテム3

なければ、

  • ありません

という表示になる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

キラやば~っ☆ な「COTOHA DECO」作っちゃった!?よーしっ、さっそくQiitaへ投稿だーっ☆

わたし、《ことは ひかる》!
CSSとJavaScriptがだ~いすきなエンジニア。

ある日、Qiitaを眺めながらCSSを書いてたら、突然、 謎のプラットフォーム を使った キャンペーンに出会ったのっ!

…これを使えば、「自然言語処理」 できるの!?キラやば~っ☆

Qiitaではフロントエンドエンジニアたちが、おしゃれな記事を書いて共有しているらしいのだけど…

あるとき、目的をはき違えた センスのかけらもない記事 が、Qiitaに投稿されてしまったの!

「CSSの表現力をもっと伝えたい」そう強く思った瞬間、 《構文解析》 を諦めて、 《要約(β)》《感情分析》《キーワード抽出》《固有表現抽出》 の結果を使って、
文字列が長いほうから、タグ付けきの文字列に置換して、キラキラなCSSを書いていったら、
わたし、「COTOHA DECO」作っちゃった!?

よーしっ、さっそくQiitaへ投稿だーっ☆

このスクリプトの実行結果が、次のCodePenのHTMLだよっ☆
const request = require('request');
const fs = require('fs');

// flat Polyfill
if (!Array.prototype.flat) {
  Array.prototype.flat = function(depth) {
    var flattend = [];
    (function flat(array, depth) {
      for (let el of array) {
        if (Array.isArray(el) && depth > 0) {
          flat(el, depth - 1); 
        } else {
          flattend.push(el);
        }
      }
    })(this, Math.floor(depth) || 1);
    return flattend;
  };
}

const DEVELOPER_API_BASE_URL   = "https://api.ce-cotoha.com/api/dev/";
const ACCESS_TOKEN_PUBLISH_URL = "https://api.ce-cotoha.com/v1/oauth/accesstokens";
const CLIENT_ID     = "ココニアイデイカク";
const CLIENT_SECRET = "ココニシークレットカク";

const main = async () => {
  let accessToken = await getAccessToken();
  await cotohaMultiParse(accessToken, 'star');
}

const cotohaMultiParse = async (accessToken, folderName) => {
  console.log(`■${folderName} のフォルダに対する処理を実施します。`);
//  let document = fs.readFileSync(`${folderName}/00_raw.txt`, 'utf-8');
  let document = `
わたし、《星奈ひかる》!
宇宙と星座がだ~いすきな中学2年生。

星空を観察しながらノートに星座を描いていたら
とつぜん謎の生物《フワ》がワープしてきたのっ!
それから、空からロケットが落ちてきて、
宇宙人の《ララ》と《プルンス》までやってきた!
…あなたたち、ホンモノの宇宙人!?キラやば~っ☆

地球から遠くとおく離れた《星空界》の
中心部にある聖域《スターパレス》では
《12星座のスタープリンセスたち》が
全宇宙の均衡を保っていたらしいのだけど…
あるとき何者かに襲われて、プリンセスたちは
《12本のプリンセススターカラーペン》になって
宇宙に散らばってしまったの!
このままじゃ星が消えて、地球も宇宙も、闇に飲み込まれちゃう…!

『星々の輝きが失われし時、
トゥインクルブックと共に現る戦士プリキュアが再びの輝きを取り戻す』
ララ達は宇宙に古くから伝わる伝説を頼りに
プリンセスが最後に生み出した希望・フワと一緒に
《伝説の戦士・プリキュア》を探していたんだって。

そこへ宇宙の支配を目論むノットレイダーがフワを狙って襲いかかってきて…
「フワを助けたい!」そう強く思った瞬間、《トゥインクルブック》から
《スターカラーペンダント》と《変身スターカラーペン》が現れて、
わたし、プリキュアに変身しちゃった!?

宇宙に散らばったプリンセススターカラーペンを集めて、
スタープリンセス復活の鍵となるフワを育てなきゃ!
よーしっ、地球を飛び出して宇宙へ出発だーっ☆
`

  let summary = await getSummary(accessToken, folderName,document.replace(/\n/g, ""), 3); // 改行を文区切り扱いするため。
  let summaries = summary.split('').filter(s =>s.length > 0);
  let ne = await getNe(accessToken, folderName, document);
  let keyword = await getKeyword(accessToken, folderName, document);
  let sentiment = await getSentiment(accessToken, folderName, document);
  // apiの結果は主に全角なため、置換を繰り返してタグをつけても問題ない前提(ちゃんとやる場合も、事前処理や全角/半角を工夫して利用すれば処理できるか)
  // キーワードは長いものから処理をしないと、置換したタグで分割されてしまうことに注意
  const getStarTag = form => {
    let num = Math.floor((form.length - 2) / 2) + 1;
    let ret = []
    for (let i = 0; i < num; i++) {
      let animeRotate = `anime-rotate-${Math.floor(Math.random() * 3) + 1}-${Math.floor(Math.random() * 3) + 1}`;
      let color = `color${Math.floor(Math.random() * 4) + 1}`;
      ret.push(`<span class="star" style="left: ${((i * 2)+ (Math.random() * 1.4) - 0.8).toFixed(3)}em; top: ${((Math.random() * 1.2) - 0.6).toFixed(3)}em;"><span class="star-base bk"><span class="star-raw bk ${animeRotate} ${color}"></span></span><span class="star-base"><span class="star-raw ${animeRotate} ${color}"></span></span></span>`);
    }
    return ret.join('');
  }
  const getKiraTag = form => {
    let num = form.length;
    let ret = []
    for (let i = 0; i < num; i++) {
      let animeFlash = `anime-flash-${Math.floor(Math.random() * 4) + 1}-${Math.floor(Math.random() * 3) + 1}`;
      ret.push(`<span class="kira" style="left: ${((i)+ (Math.random() * 1.6) - 0.8).toFixed(3)}em; top: ${((Math.random() * 1.8) - 0.9).toFixed(3)}em;"><span class="kira-raw-1 ${animeFlash}"></span><span class="kira-raw-2 ${animeFlash}"></span></span>`);
    }
    return ret.join('');
  }
  let kira = ``
  let total = [
    summaries.map( s => { return { form: s, after: `<span class="summary">${s}</span>` } }),
    ne.map( n => { return { form: n.form, after: `<span class="ne ne-${n.class}">${n.form}</span>` } }),
    keyword.map( k => { return { form: k.form, after: `<span class="keyword" data-score="${k.score}">${getStarTag(k.form)}${k.form}</span>` } }),
    sentiment.emotional_phrase.filter(s => s.emotion === 'P' || s.emotion === 'PN' || s.emotion === '喜ぶ').map( e => { return { form: e.form, after: `<span class="emotion">${getKiraTag(e.form)}${e.form}</span>` } }),
  ].flat().sort( (a, b) => b.form.length - a.form.length );
  total.forEach( s => {
    document = document.replace(new RegExp(s.form, 'gi'), s.after)
  });
  console.log(document)
  document = document.split('\n').map(d => d.length > 0 ? `<div><span class="sentence">${d}</span></div>` : '<br/>').join('');
  // hmlt作成処理
  fs.writeFileSync(`${folderName}/${folderName}.html`, `
<html>
  <head>
    <meta charset="UTF-8">
    <title>${folderName}</title>
    <style>
      body {
        background: repeating-linear-gradient(38deg, rgb(255, 174, 201, 0.4), rgb(255, 174, 201, 0.4) 24px, rgb(255, 64, 128, 0.4) 24px, rgb(255, 64, 128, 0.4) 48px);
        font-family:"ヒラギノ丸ゴ Pro W4","ヒラギノ丸ゴ Pro","Hiragino Maru Gothic Pro","ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic Pro","HG丸ゴシックM-PRO","HGMaruGothicMPRO";
        line-height: 2.2em
      }
      div {
        text-align:center
      }
      br{
        line-height: 1em;
      }
      span.sentence {
        background: linear-gradient(transparent, rgb(255, 255, 255, 0.4) 16%, rgb(255, 255, 255, 0.5) 50%, rgb(255, 255, 255, 0.4) 16%, transparent);
        padding: 8px 8px;
        border-radius: 16px;
        z-index: 100;
      }
      .summary {
        font-size: 1.6em;
        background: linear-gradient(transparent, rgb(255, 255, 255, 0.4) 20%, rgb(255, 255, 255, 0.5) 50%, rgb(255, 255, 255, 0.4) 80%, transparent);
        margin: 0px -8px;
        padding: 8px 8px;
        border-radius: 4px;
      }
      .ne {
        font-weight: bold;
        color: rgb(255, 83, 169);
      }
      .keyword {
        position: relative;
      }
      .emotion {
        position: relative;
      }
      .ne {
        position: relative;
      }
.star {
  position: absolute;
}
.star-base {
  top: 2px;
  left: 3px;
  height: 16px;
  width: 16px;
  position: absolute;
  overflow:hidden;
  border-radius: 8px;
}
.star-base.bk {
  top: 0px;
  left: 0px;
  height: 21px;
  width: 21px;
  border-radius: 10px;
}
.star-raw {
  margin: 10px;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    display: block;
    height: 0;
    width: 0;
    position: absolute;
    left: -12px;
    top: -6px;
    z-index: -1;
}
.star-raw.color1 {
    border-bottom: 7px solid rgba(251, 176, 4, 1);
}
.star-raw.color2 {
    border-bottom: 7px solid rgba(5, 186, 159, 1);
}
.star-raw.color3 {
    border-bottom: 7px solid rgba(33, 138, 254, 1);
}
.star-raw.color4 {
    border-bottom: 7px solid rgba(255, 45, 150, 1);
}
.star-raw:before,
.star-raw:after {
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    content: '';
    display: block;
    height: 0;
    left: -10px;
    position: absolute;
    top: 0;
    width: 0;
    z-index: -1;
}
.star-raw.color1:before,
.star-raw.color1:after {
    border-bottom: 7px solid rgba(251, 176, 4, 1);
}
.star-raw.color2:before,
.star-raw.color2:after {
    border-bottom: 7px solid rgba(5, 186, 159, 1);
}
.star-raw.color3:before,
.star-raw.color3:after {
    border-bottom: 7px solid rgba(33, 138, 254, 1);
}
.star-raw.color4:before,
.star-raw.color4:after {
    border-bottom: 7px solid rgba(255, 45, 150, 1);
}

.star-raw:before {
    transform: rotate(71deg);
}
.star-raw:after {
    transform: rotate(-71deg);
}

.star-raw.bk {
  margin: 12px;
    border-left: 13px solid transparent;
    border-right: 13px solid transparent;
    border-bottom: 10px solid rgba(255, 233, 182, 0.4);
    left: -14px;
    top: -8px;
}
.star-raw.bk:before,
.star-raw.bk:after {
    border-left: 13px solid transparent;
    border-right: 13px solid transparent;
    border-bottom: 10px solid rgba(255, 233, 182, 0.4);
    left: -12px;
}

.anime-rotate-1-1 {
  animation: anime-rotate-1 7s linear infinite
}

.anime-rotate-1-2 {
  animation: anime-rotate-1 10s linear infinite
}

.anime-rotate-1-3 {
  animation: anime-rotate-1 30s linear infinite
}

.anime-rotate-2-1 {
  animation: anime-rotate-2 7s linear infinite
}

.anime-rotate-2-2 {
  animation: anime-rotate-2 10s linear infinite
}

.anime-rotate-2-3 {
  animation: anime-rotate-2 30s linear infinite
}

.anime-rotate-3-1 {
  animation: anime-rotate-3 7s linear infinite
}

.anime-rotate-3-2 {
  animation: anime-rotate-3 10s linear infinite
}

.anime-rotate-3-3 {
  animation: anime-rotate-3 30s linear infinite
}

@keyframes anime-rotate-1 {
    0%   { transform: rotate(35deg);}
    50%  { transform: rotate(125deg);}
    100% { transform: rotate(35deg);}
}

@keyframes anime-rotate-2 {
    0%   { transform: rotate(45deg);}
    50%  { transform: rotate(105deg);}
    100% { transform: rotate(45deg);}
}

@keyframes anime-rotate-3 {
    0%   { transform: rotate(55deg);}
    50%  { transform: rotate(175deg);}
    100% { transform: rotate(55deg);}
}

.anime-flash-1-1 {
  animation: anime-flash-1 3s linear infinite
}

.anime-flash-1-2 {
  animation: anime-flash-1 5s linear infinite
}

.anime-flash-1-3 {
  animation: anime-flash-1 10s linear infinite
}

.anime-flash-2-1 {
  animation: anime-flash-2 3s linear infinite
}

.anime-flash-2-2 {
  animation: anime-flash-2 5s linear infinite
}

.anime-flash-2-3 {
  animation: anime-flash-2 10s linear infinite
}

.anime-flash-3-1 {
  animation: anime-flash-3 3s linear infinite
}

.anime-flash-3-2 {
  animation: anime-flash-3 5s linear infinite
}

.anime-flash-3-3 {
  animation: anime-flash-4 10s linear infinite
}

.anime-flash-4-1 {
  animation: anime-flash-4 3s linear infinite
}

.anime-flash-4-2 {
  animation: anime-flash-4 50s linear infinite
}

.anime-flash-4-3 {
  animation: anime-flash-4 10s linear infinite
}
@keyframes anime-flash-1 {
    0%   { opacity: 1;}
    10%   { opacity: 0.2;}
    90%  { opacity: 0.2;}
    100% { opacity: 1;}
}

@keyframes anime-flash-2 {
    0%   { opacity: 0.2;}
    20%  { opacity: 1;}
    40% { opacity: 0.2;}
    100% { opacity: 0.2;}
}

@keyframes anime-flash-3 {
    0%   { opacity: 0.2;}
    45%  { opacity: 0.2;}
    75% { opacity: 1;}
    95% { opacity: 0.2;}
    100% { opacity: 0.2;}
}

@keyframes anime-flash-4 {
    0%   { opacity: 0.2;}
    40%   { opacity: 0.2;}
    50%  { opacity: 1;}
    60%  { opacity: 0.2;}
    100% { opacity: 0.2;}
}

.kira {
  position: absolute;
}
.kira-raw-1 {
  margin: 10px;
    display: block;
    height: 0;
    width: 0;
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
}
.kira-raw-1:before,
.kira-raw-1:after {
    border-left: 2px solid transparent;
    border-right: 2px solid transparent;
    border-bottom: 10px solid rgba(255, 255, 0, 1);
    content: '';
    display: block;
    height: 0;
    left: -2px;
    position: absolute;
    width: 0;
    z-index: -1;
}
.kira-raw-1:after {
    top: 10px;
    transform: rotate(180deg);
}
.kira-raw-2 {
  margin: 10px;
    display: block;
    height: 0;
    width: 0;
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
}
.kira-raw-2:before,
.kira-raw-2:after {
    border-right:8px solid rgba(255, 255, 0, 1);
    border-top: 2px solid transparent;
    border-bottom: 2px solid transparent;
    content: '';
    display: block;
    height: 0;
    left: -8px;
    top: 8px;
    position: absolute;
    width: 0;
    z-index: -1;
}
.kira-raw-2:after {
    left: 0px;
    transform: rotate(180deg);
}
    </style>
  </head>
  <body>
    <div class="background"></div>
      ${document}

  </body>
</html>
`);
  return document;
}

const getAccessToken = () => {
  return new Promise((resolve, reject) => {
    request(
      {
        url: ACCESS_TOKEN_PUBLISH_URL,
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        json: {
          grantType: "client_credentials",
          clientId: CLIENT_ID,
          clientSecret: CLIENT_SECRET,
        },
      },
      (error, response, body) => {
        if (!error && (response.statusCode === 200 || response.statusCode === 201)) {
          if (typeof body !== 'object') body = JSON.parse(body);
          resolve(body.access_token);
        } else {
          if (error) {
            console.log(`request fail. error: ${error}`);
          } else {
            console.log(`request fail. response.statusCode: ${response.statusCode}, ${body}`);
          }
          reject(body);
        }
      },
    );
  });
}

const getCommonRequest = (url ,fileName, getRequestJsonFunc) => (accessToken, folderName, document) => {
  let promise;
  promise = new Promise((resolve, reject) => {
    let filePath = `${folderName}/${fileName}`;
    if (fs.existsSync(filePath)) {
      resolve(JSON.parse(fs.readFileSync(filePath, 'utf-8')));
    } else {
      request(
        {
          url: `${DEVELOPER_API_BASE_URL}${url}`,
          method: 'POST',
          headers: { 'Content-Type': 'application/json;charset=UTF-8', Authorization: `Bearer ${accessToken}`},
          json: getRequestJsonFunc(document),
        },
        (error, response, body) => {
          if (!error && (response.statusCode === 200 || response.statusCode === 201)) {
            if (typeof body !== 'object') body = JSON.parse(body);
            if (body.status === 0) {
              fs.writeFileSync(`${filePath}`, JSON.stringify(body.result, null, '  '));
              resolve(body.result);
            } else {
              console.log(`request coreference fail. error: ${body.message}`);
              reject(body);
            }
          } else {
            if (error) {
              console.log(`request ${url} fail. error: ${error}`);
            } else {
              msg = (typeof body !== 'object') ? body : JSON.stringify(body);
              console.log(`request ${url} fail. response.statusCode: ${response.statusCode}, ${msg}`);
            }
            reject(body);
          }
        }
      );
    } 
  });
  return promise;

}

const getNe = (accessToken, folderName, document) => {
  return getCommonRequest('nlp/v1/ne', '20_ne_raw.json', document => {
    return { sentence: document };
  })(accessToken, folderName, document);
}

const getKeyword = (accessToken, folderName, document) => {
  return getCommonRequest('nlp/v1/keyword', '50_keyword_raw.json', document => {
    return {
      document: document,
      max_keyword_num: 8,
    };
  })(accessToken, folderName, document);
}

const getSentiment = (accessToken, folderName, document) => {
  return getCommonRequest('nlp/v1/sentiment', '60_sentiment_raw.json', document => {
    return { sentence: document };
  })(accessToken, folderName, document);
}

const get3Summary = async (accessToken, folderName, document) => {
  let summary1 = await getSummary(accessToken, folderName, document, 1);
  let summary2 = await getSummary(accessToken, folderName, document, 2);
  let summary3 = await getSummary(accessToken, folderName, document, 3);
  let summary2Part = summary2.replace(summary1, '');
  let summary2Array = summary2Part.split('').filter(v => v.length > 0).map(v => v + '');
  let summary3Part = summary3.replace(summary1, '');
  summary2Array.forEach(s => {
    summary3Part = summary3Part.replace(s, '');
  });
  let summary3Array = summary3Part.split('').filter(v => v.length > 0).map(v => v + '');
  // summary1と、summary2とsummary3は。で区切られた、1文、2文、3文にはなっているが、
  // summary2にsummary1が含まれないこともある。
  return [ [ { form: summary1, sent_len: 1 } ] , summary2Array.map(s => { return { form: s, sent_len: 2}; } ), summary3Array.map(s => { return { form: s, sent_len: 3}; } )].flat();
}

const getSummary = (accessToken, folderName, document, i) => {
  return getCommonRequest('nlp/beta/summary', `40_summary_${i}_raw.json`, document => {
    return {
      document: document,
      sent_len: i,
    };
  })(accessToken, folderName, document);
}

main();

See the Pen NWqaGWe by j5c8k6m8 (@j5c8k6m8) on CodePen.

参考リンク

スター☆トゥインクルプリキュア 作品情報 - 東映アニメーション

CSSだけで色々な星を再現する(おまけ付き) - Qiita

角丸の三角形をcssで作りたい - teratail

おまけ

ラグビーW杯 決勝のニュース

https://www.nikkei.com/article/DGXMZO51758280S9A101C1000000/

See the Pen abOLvmB by j5c8k6m8 (@j5c8k6m8) on CodePen.

外郎売

See the Pen gOpGaMj by j5c8k6m8 (@j5c8k6m8) on CodePen.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む