この記事は次の機能に分かれています。
- tinymce 初期化のためのいくつかの設定
- ツールバーとテキストの間に特定のタイトルと概要を挿入します。
- ツールバーのボタンをカスタマイズして特定の機能を実現する
- 写真アップロード時のネットワークアップロード機能を削除
- 貼り付けた画像はデフォルトでアップロードされます
- 写真に透かし機能を追加する
- ワンクリック組版を実現
1. tinymce 初期化のいくつかの構成
1. まず、次の 2 つのプラグインを導入する必要があります
cnpm install @tinymce/tinymce-vue --save バージョン: 2.0.0
cnpm install tinymce --save バージョン: 5.0.3
注: 以前使用したとき、tinymce 6 以降のバージョンには一部の組み込みプラグインが存在しないことがわかり、一部の機能が使用できなくなったので、バージョンはこちら
2. プラグインをダウンロードした後、node_modules で tinymce フォルダーを見つけ、その中にある Skins フォルダーをコピーして、vue プロジェクトのパブリック フォルダーに配置する必要があります。
3. プラグインを中国語に翻訳するには、言語パックもダウンロードする必要があります。ダウンロード アドレスは次のとおりです。
公式サイトアドレス: https: //www.tiny.cloud/get-tiny/ language-packages/
次のように、ダウンロードする zh-ch を見つけます。
その後、ダウンロードした言語パックを vue のパブリック フォルダーに配置し、コードに導入します。ダウンロードした言語パックの名前は zh-Hans で、他の言語パックとは異なる場合がありますが、最終的な効果は同じです。同じように、ファイル名に従って直接インポートするだけです
以下は、導入されたコード、いくつかのプラグイン、およびいくつかの基本構成です。
<template>
<div class="editor_wraper">
<editor :init="tinymceInit" v-model="content"> </editor>
</div>
</template>
<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
toolbar,
fontsizeFormats,
fontFormats,
lineheightFormats,
} from "@/utils/tinymceConfig";
export default {
data() {
return {
content: "",
tinymceInit: {
language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
language: "zh-Hans", //语言类型
skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
quickbars_image_toolbar: "", // 选中媒体文件时的弹框
// skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
toolbar: toolbar, //工具栏配置,设为false则隐藏
menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
height: 500, // 富文本高度
model: 'dom', // 是否可拉伸富文本框
fontsize_formats: fontsizeFormats, //字体大小
font_formats: fontFormats, //字体样式
lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
placeholder: "在这里输入文字",
branding: false, //tiny技术支持信息是否显示
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
paste_data_images: true, //图片是否可粘贴
elementpath: false, //元素路径是否显示
},
};
},
components: { Editor },
};
</script>
上記で紹介した tinymceConfig ファイルの構成をいくつか示します。
/**
* @description: 工具栏配置
* @return {*}
*/
export const toolbar = `
undo redo restoredraft |
removeformat|
formatselect |
subscript superscript |
bold italic underline strikethrough link anchor |
numlist bullist blockquote |
alignleft aligncenter alignright alignjustify|
quicklink searchreplace image|
forecolor backcolor |
fontselect fontsizeselect|
outdent indent lineheight|`
/**
* @description: 字体大小设置
* @return {*}
*/
export const fontsizeFormats = `12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px`
/**
* @description: 字体设置
* @return {*}
*/
export const fontFormats = `微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;`
/**
* @description: 行高设置
* @return {*}
*/
export const lineheightFormats = "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5"
上記のコンテンツを構成すると、ページに次の効果が表示される場合があります
2. ツールバーとテキストの間に特定のタイトルと要約を挿入します。
タイトルと要約を挿入する方法は、次のようにインライン モードを使用してそれを実現することです。上記のコードに基づいて変更しました。
注: インライン モードを有効にした後、toolbar_persist を true に設定した場合でも、固定表示ではなくツールバーを表示するには tinymce をクリックする必要があります。前に npm アンインストールで削除したときに tinymce パッケージを削除しなかった可能性があります。 .node_modulesには多くのtinymceパッケージが存在します.このとき、node_modules全体を削除してから、再度インストールする必要があります.個人テストの落とし穴
<template>
<div class="editor_wraper">
<div id="mytoolbar"></div>
<el-input
class="titleStyle"
v-model="defaultTitle"
type="textarea"
resize="none"
:autosize="{ minRows: 1, maxRows: 3 }"
placeholder="请在这里输入标题"
></el-input>
<el-input
class="abstractStyle"
v-model="defaultAbstract"
type="textarea"
resize="none"
:autosize="{ minRows: 1 }"
placeholder="摘要(可选)"
></el-input>
<editor :init="tinymceInit" v-model="content"> </editor>
</div>
</template>
<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
toolbar,
fontsizeFormats,
fontFormats,
lineheightFormats,
} from "@/utils/tinymceConfig";
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
data() {
return {
defaultTitle: "",
defaultAbstract: "",
content: "",
tinymceInit: {
language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
language: "zh-Hans", //语言类型
skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
quickbars_image_toolbar: "", // 选中媒体文件时的弹框
// skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
toolbar: toolbar, //工具栏配置,设为false则隐藏
menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
height: 500, // 富文本高度
model: 'dom', // 是否可拉伸富文本框
fontsize_formats: fontsizeFormats, //字体大小
font_formats: fontFormats, //字体样式
lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
placeholder: "在这里输入文字",
branding: false, //tiny技术支持信息是否显示
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
paste_data_images: true, //图片是否可粘贴
elementpath: false, //元素路径是否显示
inline: true, //使用内联模式
toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
},
};
},
components: { Editor },
};
</script>
<style lang="scss">
.editor_wraper {
width: 60%;
height: 80vh;
margin: 0 auto;
}
.mce-content-body{
height: 100%;
outline: none;
}
.titleStyle .el-textarea__inner {
width: 100%;
height: 56px;
font-size: 24px;
font-weight: 500;
margin-top: 10px;
padding-left: 0;
border: none;
}
.abstractStyle .el-textarea__inner {
font-size: 22px;
font-weight: 500;
color: #bbb;
margin-top: 5px;
padding-left: 0;
border: none;
}
</style>
マッチング後、以下の効果が表示されます
3. ツールバーのボタンをカスタマイズして特定の機能を実現する
カスタム ボタンを作成するには、次の 3 つの手順があります。
1. tinymceConfig ファイルにメソッドを作成します
/**
* @description: 自定义按钮
* @param {*} editor
* @return {*}
*/
export const customBtn = (editor) => {
// 参数一:自定义名称,需要放置在工具栏中
editor.ui.registry.addButton("customBtn", {
icon: "brightness", // 显示的图标
tooltip: '自定义按钮', // 提示文字
onAction: function () {
console.log("点击了自定义按钮")
}
})
}
2. tinymce 設定で参照します。
3. addButton で宣言したカスタム名をツールバーに配置します。
最後に作成したボタンが表示されます。
注: アイコンを変更したい場合は、公式 Web サイトに記載されているいくつかのアイコン アドレスを参照できます
: https://www.tiny.cloud/docs/tinymce/6/editor-icon-identifiers/
4.写真アップロード時のネットワークアップロード機能を削除する
いわゆる削除とは、画像アップロードを自分でカスタマイズし直すという意味です tinymce では画像アップロードを使用していません カスタムボタンは上記の方法で作成できます ここでは画像アップロード方法のみ書きます
/**
* @description: 自定义图片上传
* @param {*} editor
* @return {*}
*/
export const imageUpload = (editor) => {
editor.ui.registry.addButton("imageUpload", {
icon: "image",
tooltip: '上传图片',
onAction: function () {
var input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.onchange = function () {
var file = this.files[0];
if (file.size / 1024 / 1024 > 20) {
failure("上传失败,图片大小请控制在 20M 以内");
} else {
let formData = new FormData();
formData.append("picture", file);
formData.append("action", "add");
// 上传后的逻辑
uploadImage({ formData }).then((res) => {
var reader = new FileReader();
reader.onload = function () {
var id = "blobid" + new Date().getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(",")[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
// 将图片插入到文本中
editor.insertContent(`<img src="${blobInfo.blobUri()}"/>`);
};
reader.readAsDataURL(file);
}).catch(() => {
failure("上传出错,服务器开小差了");
});
}
};
// 触发上传
input.click();
},
});
}
5. 貼り付けた画像はデフォルトでアップロードできます
貼り付けとコピー機能を使用するには、ページに直接貼り付けプラグインを導入する必要があります
import "tinymce/plugins/paste"; インポートして、設定用の設定にプラグインを追加するだけです
次に、構成内のpaste_postprocessを通じてコピーされたコンテンツを監視し、貼り付けたロジックをpaste_postprocessに書き込みます。
<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
toolbar,
fontsizeFormats,
fontFormats,
lineheightFormats,
customBtn,
imageUpload,
} from "@/utils/tinymceConfig";
import "tinymce/plugins/paste"; // 复制粘贴的插件
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
data() {
return {
defaultTitle: "",
defaultAbstract: "",
content: "",
tinymceInit: {
language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
language: "zh-Hans", //语言类型
skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
quickbars_image_toolbar: "", // 选中媒体文件时的弹框
plugins: "paste", //插件配置
// skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
toolbar: toolbar, //工具栏配置,设为false则隐藏
menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
height: 500, // 富文本高度
model: "dom", // 是否可拉伸富文本框
fontsize_formats: fontsizeFormats, //字体大小
font_formats: fontFormats, //字体样式
lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
placeholder: "在这里输入文字",
branding: false, //tiny技术支持信息是否显示
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
paste_data_images: true, //图片是否可粘贴
elementpath: false, //元素路径是否显示
inline: true, // 使用内联模式
toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
// 粘贴内容时的回调
paste_postprocess: (plugin, args) => {
this.$nextTick(() => {
// 获取当前编辑器标签
const doc = tinymce.activeEditor.getBody();
// 循序所有标签
doc.childNodes.forEach(async (item) => {
const tag = item.firstChild; // 获取当前标签下的第一个标签
// 判断当前标签或当前标签下面的第一个标签是否是一个img
if (item.localName === "img" || tag.localName === "img") {
const src =
item.localName === "img"
? item.getAttribute("src")
: tag.getAttribute("src");
// 如果是则拿到当前标签的图片地址,传递给后端,进行保存
const { data } = await uploadImgByUrl({ url: src });
// 拼接后端保存后的图片地址
const url = process.env.VUE_APP_BASE_API + data;
// 然后将新地址重新赋值给img标签
item.localName === "img"
? item.setAttribute("src", url)
: tag.setAttribute("src", url);
}
});
});
},
// 自定义工具栏配置
setup: function (editor) {
// 自定义图片上传功能
customBtn(editor);
// 图片上传
imageUpload(editor);
},
},
};
},
components: { Editor },
};
</script>
6. 画像に透かし機能を追加する
また、ウォーターマークを追加する機能を実現するためのカスタム ボタンも作成しました。ここでのウォーターマークの追加とは、記事内のすべての画像にウォーターマークを追加することです。個別のニーズがある場合は、自分で変更できます。上記を表示するにはカスタム ボタンを作成します道
画像の数が多すぎる場合、ウォーターマークを追加するのに少し時間がかかる場合があります。ローディング状態を追加することをお勧めします
/**
* @description: 添加图片水印
* @param {*} editor
* @return {*}
*/
export const imageWatermark = (editor) => {
editor.ui.registry.addButton("imageWatermark", {
icon: "edit-image",
tooltip: '添加图片水印',
onAction: function () {
const doc = tinymce.activeEditor.getBody()
doc.childNodes.forEach(item => {
const tag = item.firstChild
// 单独修改img标签
if (item.localName === "img" || tag.localName === "img") {
editImages(tag)
}
})
}
})
}
/**
* @description: 给图片添加水印
* @param {*} child
* @return {*}
*/
const editImages = (child) => {
const src = child.getAttribute("src")
var image = new Image();
image.crossOrigin = 'anonymous';
image.src = src;
image.onload = async () => {
// 创建canvas,并将创建的img绘制成canvas
const canvas = document.createElement('canvas')
canvas.width = child.width
canvas.height = child.height
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0)
ctx.textAlign = "left"
ctx.textBaseline = "top"
ctx.font = "18px Microsoft Yahei"
ctx.fillStyle = "rgba(255, 255, 255, 0.5)"
ctx.rotate((Math.PI / 180) * 15)
for (let i = 0; i < child.height / 120; i++) {
for (let j = 0; j < child.width / 50; j++) {
ctx.fillText("这是水印", i * 200, j * 100, child.width)
}
}
const base64Url = canvas.toDataURL()
setTimeout(() => {
// 将添加好水印的图片重新插入到富文本中
child.setAttribute("src", base64Url)
}, 5000)
}
}
7. ワンキー写植を実現
ワンクリック写植方式でもカスタムボタンを作成しますが、実装方法は基本的に同じで、domノードを取得した後、対応するノードラベルを判定し、対応するラベルに異なるスタイルを追加します。
/**
* @description: 一键排版
* @param {*} editor
* @return {*}
*/
const objLabel = {
"h1": "title",
"h2": "title",
"h3": "title",
"p": "paragraph"
}
const objStyle = {
title: {
"font-family": "微软雅黑",
"font-size": "22px"
},
paragraph: {
"font-size": "16px",
"color": "red"
}
}
export const oneClickLayout = (editor) => {
// 参数一:自定义名称,需要放置在工具栏中
editor.ui.registry.addButton("oneClickLayout", {
icon: "orientation", // 显示的图标
tooltip: '一键布局', // 提示文字
onAction: function () {
const doc = tinymce.activeEditor.getBody()
doc.childNodes.forEach(item => {
// 获取需要修改的标签
const text = objLabel[item.localName]
if (text) {
// 找到对应样式循环进行配置
for (let v in objStyle[text]) {
item.style[v] = objStyle[text][v]
}
}
})
}
})
}
この時点で、すべての関数が完了しました。関数全体のコードを以下に添付します。
<template>
<div class="editor_wraper">
<div id="mytoolbar"></div>
<el-input
class="titleStyle"
v-model="defaultTitle"
type="textarea"
resize="none"
:autosize="{ minRows: 1, maxRows: 3 }"
placeholder="请在这里输入标题"
></el-input>
<el-input
class="abstractStyle"
v-model="defaultAbstract"
type="textarea"
resize="none"
:autosize="{ minRows: 1 }"
placeholder="摘要(可选)"
></el-input>
<editor :init="tinymceInit" v-model="content"> </editor>
</div>
</template>
<script>
import tinymce from "tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import {
toolbar,
fontsizeFormats,
fontFormats,
lineheightFormats,
customBtn,
imageUpload,
oneClickLayout
} from "@/utils/tinymceConfig";
import "tinymce/plugins/paste";
import "tinymce/icons/default"; // 方式工具栏的icon乱码
export default {
data() {
return {
defaultTitle: "",
defaultAbstract: "",
content: "",
tinymceInit: {
language_url: "tinymce/langs/zh-Hans.js", //引入语言包文件
language: "zh-Hans", //语言类型
skin_url: "tinymce/skins/ui/oxide", //皮肤:浅色
quickbars_image_toolbar: "", // 选中媒体文件时的弹框
plugins: "paste", //插件配置
// skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色
toolbar: toolbar, //工具栏配置,设为false则隐藏
menubar: false, //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
height: 500, // 富文本高度
model: "dom", // 是否可拉伸富文本框
fontsize_formats: fontsizeFormats, //字体大小
font_formats: fontFormats, //字体样式
lineheight_formats: lineheightFormats, //行高配置,也可配置成"12px 14px 16px 20px"这种形式
placeholder: "在这里输入文字",
branding: false, //tiny技术支持信息是否显示
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
paste_data_images: true, //图片是否可粘贴
elementpath: false, //元素路径是否显示
inline: true, // 使用内联模式
toolbar_persist: true, // 在内联模式中,工具栏是否自动显示和隐藏
fixed_toolbar_container: "#mytoolbar", // 将工具栏显示在一个固定的html元素上
// 粘贴内容时的回调
paste_postprocess: (plugin, args) => {
this.$nextTick(() => {
// 获取当前编辑器标签
const doc = tinymce.activeEditor.getBody();
// 循序所有标签
doc.childNodes.forEach(async (item) => {
const tag = item.firstChild; // 获取当前标签下的第一个标签
// 判断当前标签或当前标签下面的第一个标签是否是一个img
if (item.localName === "img" || tag.localName === "img") {
const src =
item.localName === "img"
? item.getAttribute("src")
: tag.getAttribute("src");
// 如果是则拿到当前标签的图片地址,传递给后端,进行保存
const { data } = await uploadImgByUrl({ url: src });
// 拼接后端保存后的图片地址
const url = process.env.VUE_APP_BASE_API + data;
// 然后将新地址重新赋值给img标签
item.localName === "img"
? item.setAttribute("src", url)
: tag.setAttribute("src", url);
}
});
});
},
// 自定义工具栏配置
setup: function (editor) {
// 自定义图片上传功能
customBtn(editor);
// 图片上传
imageUpload(editor);
// 一键布局
oneClickLayout(editor)
},
},
};
},
components: { Editor },
};
</script>
<style lang="scss">
.editor_wraper {
width: 60%;
height: 80vh;
margin: 0 auto;
}
.mce-content-body {
height: 100%;
outline: none;
}
.titleStyle .el-textarea__inner {
width: 100%;
height: 56px;
font-size: 24px;
font-weight: 500;
margin-top: 10px;
padding-left: 0;
border: none;
}
.abstractStyle .el-textarea__inner {
font-size: 22px;
font-weight: 500;
color: #bbb;
margin-top: 5px;
padding-left: 0;
border: none;
}
</style>
tinymceConfig ファイルのコードは次のとおりです。
/**
* @description: 工具栏配置
* @return {*}
*/
export const toolbar = `
customBtn imageUpload oneClickLayout|
undo redo restoredraft |
removeformat|
formatselect |
subscript superscript |
bold italic underline strikethrough link anchor |
numlist bullist blockquote |
alignleft aligncenter alignright alignjustify|
quicklink searchreplace image|
forecolor backcolor |
fontselect fontsizeselect|
outdent indent lineheight|`
/**
* @description: 字体大小设置
* @return {*}
*/
export const fontsizeFormats = `12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px`
/**
* @description: 字体设置
* @return {*}
*/
export const fontFormats = `微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;`
/**
* @description: 行高设置
* @return {*}
*/
export const lineheightFormats = "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5"
/**
* @description: 自定义按钮
* @param {*} editor
* @return {*}
*/
export const customBtn = (editor) => {
// 参数一:自定义名称,需要放置在工具栏中
editor.ui.registry.addButton("customBtn", {
icon: "brightness", // 显示的图标
tooltip: '自定义按钮', // 提示文字
onAction: function () {
console.log("点击了自定义按钮")
}
})
}
/**
* @description: 自定义图片上传
* @param {*} editor
* @return {*}
*/
export const imageUpload = (editor) => {
editor.ui.registry.addButton("imageUpload", {
icon: "image",
tooltip: '上传图片',
onAction: function () {
var input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.onchange = function () {
var file = this.files[0];
if (file.size / 1024 / 1024 > 20) {
failure("上传失败,图片大小请控制在 20M 以内");
} else {
let formData = new FormData();
formData.append("picture", file);
formData.append("action", "add");
// 上传后的逻辑
uploadImage({ formData }).then((res) => {
var reader = new FileReader();
reader.onload = function () {
var id = "blobid" + new Date().getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(",")[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
// 将图片插入到文本中
editor.insertContent(`<img src="${blobInfo.blobUri()}"/>`);
};
reader.readAsDataURL(file);
}).catch(() => {
failure("上传出错,服务器开小差了");
});
}
};
// 触发上传
input.click();
},
});
}
/**
* @description: 一键排版
* @param {*} editor
* @return {*}
*/
const objLabel = {
"h1": "title",
"h2": "title",
"h3": "title",
"p": "paragraph"
}
const objStyle = {
title: {
"font-family": "微软雅黑",
"font-size": "22px"
},
paragraph: {
"font-size": "16px",
"color": "red"
}
}
export const oneClickLayout = (editor) => {
// 参数一:自定义名称,需要放置在工具栏中
editor.ui.registry.addButton("oneClickLayout", {
icon: "orientation", // 显示的图标
tooltip: '一键布局', // 提示文字
onAction: function () {
const doc = tinymce.activeEditor.getBody()
doc.childNodes.forEach(item => {
// 获取需要修改的标签
const text = objLabel[item.localName]
if (text) {
// 找到对应样式循环进行配置
for (let v in objStyle[text]) {
item.style[v] = objStyle[text][v]
}
}
})
}
})
}
/**
* @description: 添加图片水印
* @param {*} editor
* @return {*}
*/
export const imageWatermark = (editor) => {
editor.ui.registry.addButton("imageWatermark", {
icon: "edit-image",
tooltip: '添加图片水印',
onAction: function () {
const doc = tinymce.activeEditor.getBody()
doc.childNodes.forEach(item => {
const tag = item.firstChild
// 单独修改img标签
if (item.localName === "img" || tag.localName === "img") {
editImages(tag)
}
})
}
})
}
/**
* @description: 给图片添加水印
* @param {*} child
* @return {*}
*/
const editImages = (child) => {
const src = child.getAttribute("src")
var image = new Image();
image.crossOrigin = 'anonymous';
image.src = src;
image.onload = async () => {
// 创建canvas,并将创建的img绘制成canvas
const canvas = document.createElement('canvas')
canvas.width = child.width
canvas.height = child.height
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0)
ctx.textAlign = "left"
ctx.textBaseline = "top"
ctx.font = "18px Microsoft Yahei"
ctx.fillStyle = "rgba(255, 255, 255, 0.5)"
ctx.rotate((Math.PI / 180) * 15)
for (let i = 0; i < child.height / 120; i++) {
for (let j = 0; j < child.width / 50; j++) {
ctx.fillText("这是水印", i * 200, j * 100, child.width)
}
}
const base64Url = canvas.toDataURL()
setTimeout(() => {
child.setAttribute("src", base64Url)
}, 5000)
}
}
これは tinymce を使用中に経験したことですが、これを実現するまでに長い時間がかかりました。