この記事ではテキスト内にあるツイッターのURLやyoutubeのURLをもとにプレビューを表示する方法をサンプルコード付きでご紹介します。
サンプルコードのデモは次の通りです。
デモではテキストエリアに入力されたツイッターのURLやyoutubeのURLを1つづつ表示します。
このプレビューの表示仕様は開発中のプロジェクトに合わせて簡単に変更することができます。
テキスト内のURLをリンクにする方法は「テキスト内のハッシュタグやURLをリンクにする」で詳しく説明しています。
サンプルコード
テキスト内のURLのプレビューを表示するサンプルコードは以下のとおりです。
import React, { useEffect, useState, useRef } from "react";
import { TwitterTweetEmbed } from "react-twitter-embed";
/**
* text内にツイッターURLが含まれているかどうかを判定する
* @param text
* @returns
*/
export const hasTwitterUrl = (text: string) => {
const regexpTweet = /(https?:\/\/twitter\.com\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+\/status\/[0-9]+)/g;
const tweet = text.match(regexpTweet);
return Boolean(tweet?.length);
};
/**
* テキスト内のツイッターURLからツイッターのEmbedコンポーネントを生成する
* @param text
* @returns
*/
export type EmbedTwitterProps = {
text: string;
};
export const EmbedTwitter: React.FC<EmbedTwitterProps> = (props) => {
const regexpTweet = /(https?:\/\/twitter\.com\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+\/status\/[0-9]+)/g;
const tweet = props.text.match(regexpTweet);
if (tweet) {
return <TwitterTweetEmbed tweetId={tweet[0].split("/")[5]} />;
}
return <></>;
};
/**
* text内にユーチューブURLが含まれているかどうかを判定する
* @param text
* @returns
*/
export const hasYoutubeUrl = (text: string) => {
const regexpYoutube = /(https?:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+)/g;
const youtube = text.match(regexpYoutube);
return Boolean(youtube?.length);
};
/**
* テキスト内のYouTubeURLからYouTubeのEmbedコンポーネントを生成する
* @param text
* @returns
*/
export type EmbedYoutubeProps = {
text: string;
};
export const EmbedYoutube: React.FC<EmbedYoutubeProps> = (props) => {
const regexpYoutube = /(https?:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+)/g;
const youtube = props.text.match(regexpYoutube);
if (youtube) {
const embedUrl = `https://www.youtube.com/embed/${
youtube[0].split("=")[1]
}`;
return (
<div
style={{ position: "relative", width: "100%", paddingTop: "56.25%" }}
>
<iframe
width="100%"
height="100%"
src={embedUrl}
frameBorder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
style={{ position: "absolute", top: 0, right: 0 }}
></iframe>
</div>
);
}
return <></>;
};
import React, { useState } from "react";
import {
hasTwitterUrl,
EmbedTwitter,
hasYoutubeUrl,
EmbedYoutube
} from "./Embed";
import { textToLink } from "./utility";
import TextField from "@mui/material/TextField";
export default function App() {
const [comment, setComment] = useState<string>("");
return (
<>
<TextField
label="コメント"
value={comment}
rows={5}
fullWidth
multiline
onChange={(e) => setComment(e.target.value)}
/>
<br />
<br />
↓URLなどをリンクに変換しプレビュー表示
<div
dangerouslySetInnerHTML={{
__html: textToLink(comment)
}}
style={{
whiteSpace: "pre-wrap",
lineHeight: "176%",
fontSize: ".9rem"
}}
/>
{hasTwitterUrl(comment) ? <EmbedTwitter text={comment} /> : null}
{hasYoutubeUrl(comment) ? <EmbedYoutube text={comment} /> : null}
</>
);
}
サンプルコードのポイントの説明
テキスト内のURLのプレビューを表示するサンプルコードのポイントとなる部分の説明をします。
ポイントとなるのは
です。
これらについて説明します。
ツイートの埋め込み
ツイートの埋め込みはEmbed.tsxの次のコードで行っています。
export const EmbedTwitter: React.FC<EmbedTwitterProps> = (props) => {
const regexpTweet = /(https?:\/\/twitter\.com\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+\/status\/[0-9]+)/g;
const tweet = props.text.match(regexpTweet);
if (tweet) {
return <TwitterTweetEmbed tweetId={tweet[0].split("/")[5]} />;
}
return <></>;
};
regexpTweetではツイートのURLを正規表現で表しています。
テキスト内のツイートのURLを取り出し、最初のツイートURLのツイートIDをtweet[0].split("/")[5]
で取得しています。
このツイートIDをTwitterTweetEmbedコンポーネントに渡してあげればツイートを埋め込むことができます。
youtubeの埋め込み
youtubeの埋め込みはEmbed.tsxの次のコードで行っています。
export const EmbedYoutube: React.FC<EmbedYoutubeProps> = (props) => {
const regexpYoutube = /(https?:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+)/g;
const youtube = props.text.match(regexpYoutube);
if (youtube) {
const embedUrl = `https://www.youtube.com/embed/${
youtube[0].split("=")[1]
}`;
return (
<div
style={{ position: "relative", width: "100%", paddingTop: "56.25%" }}
>
<iframe
width="100%"
height="100%"
src={embedUrl}
frameBorder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
style={{ position: "absolute", top: 0, right: 0 }}
></iframe>
</div>
);
}
return <></>;
};
regexpYoutubeはyoutubeの動画URLを正規表現で表しています。
テキスト内のすべてのyoutubeの動画URLを取り出し、最初の動画を埋め込んでいます。
youtubeはiframeで埋め込みますが、CSSで整えてあげないと動画を表示するアスペクト比が崩れてしまします。
youtubeを16:9を維持したままレスポンシブにするCSSは次のとおりです。
<div
style={{ position: "relative", width: "100%", paddingTop: "56.25%" }}
>
<iframe
width="100%"
height="100%"
...
style={{ position: "absolute", top: 0, right: 0 }}
></iframe>
</div>
Reactとtypescriptの参考書をまとめておきます。
コメント