emoji-line-break
Version:
Split emoji text into multiple lines.
463 lines (418 loc) • 22 kB
HTML
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="Split emoji text into multiple lines.">
<meta name="keywords" content="emoji-line-break.js, emoji-line-break">
<title>emoji-line-break.js</title>
<link rel="icon" type="image/png" sizes="32x32" href="./img/gabriel.ico">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<style type="text/css">
.navbar-brand {
font-weight: 300;
}
.navbar-brand .h6 {
font-weight: 300;
}
.ui-options .input-group {
margin-top: 10px;
}
.ui-options .input-group:first-child {
margin-top: 30px;
}
.ui-options .input-group-prepend .input-group-text {
min-width: 85px;
}
.ui-options .btn {
width: 100%;
white-space: nowrap;
}
.rcanvas {
height: auto;
border: 1px solid transparent;
}
#textarea {
margin-top: 30px;
height: calc(100% - 32px);
}
.canvas2d-switch {
user-select: none;
display: flex;
align-items: center;
}
.canvas2d-switch .custom-control-label {
margin-left: 18px;
zoom: 1.55;
}
.canvas2d-switch .custom-control-label::after, .canvas2d-switch .custom-control-label::before {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.canvas2d-switch .custom-control-input:checked~.custom-control-label::after {
background-color: #fff;
-webkit-transform: translateX(.75rem);
transform: translateX(.75rem) translateY(-50%);
}
.ui-options .input-group-custom {
margin-top: 4px;
}
.ui-unit {
margin-left: -5px;
}
.ui-unit .input-group-prepend {
margin-left: 5px;
}
.ui-unit .input-group-prepend .input-group-text {
min-width: auto;
}
@media (max-width: 1200px) {
.ui-unit {
margin-bottom: -5px;
}
.ui-unit .form-control {
min-width: 150px;
margin-bottom: 5px;
}
.ui-unit .input-group-prepend, .ui-unit .input-group-append {
margin-bottom: 5px;
}
.ui-options .input-group-prepend .input-group-text {
min-width: 85px;
}
}
@media (max-width: 992px) {
.ui-unit .form-control {
min-width: 100px;
}
.ui-options .input-group-prepend .input-group-text {
min-width: 60px;
}
}
@media (max-width: 500px) {
.ui-unit .form-control {
min-width: 200px;
}
.ui-options .input-group-prepend .input-group-text {
min-width: 85px;
}
}
</style>
</head>
<body>
<header class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="https://github.com/Yayure/emoji-line-break.js">emoji-line-break.js<small class="h6"> v1.1.2</small></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="https://github.com/Yayure/emoji-line-break.js/blob/master/README.md" id="readme">Docs </a>
</li>
</ul>
</div>
</div>
</header>
<div class="container">
<div class="row">
<div class="col-md-8">
<textarea class="form-control" rows="10" id="textarea" placeholder="input your text in here"></textarea>
</div>
<div class="col-md-4 ui-options">
<div class="input-group input-group-sm">
<span class="input-group-prepend">
<label class="input-group-text" for="lang">canvas2d</label>
</span>
<div class="custom-control custom-switch canvas2d-switch" data-toggle="tooltip" data-placement="top">
<input type="checkbox" class="custom-control-input" id="customSwitch1" checked>
<label class="custom-control-label" for="customSwitch1" ></label>
</div>
</div>
<div class="input-group input-group-sm" style="display: none;">
<span class="input-group-prepend">
<label class="input-group-text" for="lang">lang</label>
</span>
<div class="btn-group btn-group-toggle" id="lang" data-toggle="buttons">
<label class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom">
<input type="radio" name="options" value="zh"> zh
</label>
<label class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom">
<input type="radio" name="options" value="en"> en
</label>
</div>
</div>
<div class="input-group input-group-sm">
<span class="input-group-prepend">
<label class="input-group-text" for="wordBreak">wordBreak</label>
</span>
<div class="btn-group btn-group-toggle" id="wordBreak" data-toggle="buttons">
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="break-all" checked> break-all
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="break-word"> break-word
</label>
</div>
</div>
<div class="input-group input-group-sm">
<span class="input-group-prepend">
<label class="input-group-text" for="fontWeight">fontWeight</label>
</span>
<div class="btn-group btn-group-toggle" id="fontWeight" data-toggle="buttons">
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="lighter"> lighter
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="normal" checked> normal
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="bold"> bold
</label>
</div>
</div>
<div class="input-group input-group-sm input-group-custom">
<input type="text" class="form-control custom-input" id="fontWeightCustom" value="" placeholder="">
</div>
<div class="input-group input-group-sm">
<span class="input-group-prepend">
<label class="input-group-text" for="fontFamily">fontFamily</label>
</span>
<div class="btn-group btn-group-toggle" id="fontFamily" data-toggle="buttons">
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="serif"> serif
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="sans-serif" checked> sans-serif
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="Arial"> Arial
</label>
<label class="btn btn-secondary btn-sm">
<input type="radio" name="options" value="cursive"> cursive
</label>
</div>
</div>
<div class="input-group input-group-sm input-group-custom">
<input type="text" class="form-control custom-input" id="fontFamilyCustom" value="" placeholder="">
</div>
<div class="input-group input-group-sm ui-unit">
<span class="input-group-prepend">
<label class="input-group-text" for="fontSize">fontSize</label>
</span>
<input type="number" class="form-control" id="fontSize" value="16" placeholder="">
<span class="input-group-append">
<span class="input-group-text">px</span>
</span>
<span class="input-group-prepend">
<label class="input-group-text" for="width">width</label>
</span>
<input type="number" class="form-control" id="width" value="500" placeholder="">
<span class="input-group-append">
<span class="input-group-text">px</span>
</span>
</div>
<div class="input-group input-group-sm">
<button type="button" class="btn btn-primary" id="fullver">Download full ver <small>(~63.4kb)</small> </button>
</div>
<div class="input-group input-group-sm">
<button type="button" class="btn btn-primary" id="canvas2dver">Download canvas2d ver <small>(~15.3kb)</small> </button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-control rcanvas">
<hr />
<canvas width="" height="" id="canvas"></canvas>
</div>
</div>
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/emoji-line-break@1.1.2/dist/emoji-line-break.min.js"></script>
<script type="text/javascript">;
let now = new Date();
let jetLag =now.getHours() - now.getUTCHours();
let lang = (jetLag === 8 || jetLag === -16) ? 'zh' : 'en';
let model = {
defaultText: `JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。JavaScript® (часто просто JS) — это легковесный, интерпретируемый или JIT-компилируемый, объектно-ориентированный язык с функциями первого класса.JavaScript (JS) は軽量で、軽量なインタープリター型、あるいは実行時コンパイルされる、第一級関数を備えたプログラミング言語です。
☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕`,
zh: {
defaultText: `JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web 页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,例如 Node.js、 Apache CouchDB 和 Adobe Acrobat。JavaScript 是一种基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式风格。☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕`,
readme: 'https://github.com/Yayure/emoji-line-break.js/blob/master/README.ZH-CN.md',
lang_tips: '此选项在canvas2d启用时被禁用',
canvas_tips: '您可以在此选项传入CanvasRenderingContext2D',
custom_holder: {
fontFamily: '自定义输入fontFamily',
fontWeight: '自定义输入fontWeight',
}
},
en: {
defaultText: `JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions. While it is most well-known as the scripting language for Web pages, many non-browser environments also use it, such as Node.js, Apache CouchDB and Adobe Acrobat. JavaScript is a prototype-based, multi-paradigm, single-threaded, dynamic language, supporting object-oriented, imperative, and declarative styles.☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕☕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕💕`,
readme: 'https://github.com/Yayure/emoji-line-break.js/blob/master/README.ZH-CN.md',
lang_tips: 'This option is disabled when using canvas2d',
canvas_tips: 'You can pass in CanvasRenderingContext2D in this option',
custom_holder: {
fontFamily: 'custom input fontFamily',
fontWeight: 'custom input fontWeight',
}
},
fullver: {
href: './dist/emoji-line-break.min.js',
name: 'emoji-line-break.min.js'
},
canvas2dver: {
href: './dist/emoji-line-break.canvas2d.min.js',
name: 'emoji-line-break.canvas2d.min.js'
},
}
let view = {
wrap: $('.ui-options'),
allInput: $('input,textarea'),
textarea: $('#textarea'),
lang: $('#lang'),
wordBreak: $('#wordBreak'),
fontWeight: $('#fontWeight'),
fontWeightCustom: $('#fontWeightCustom'),
fontFamily: $('#fontFamily'),
fontFamilyCustom: $('#fontFamilyCustom'),
fontSize: $('#fontSize'),
width: $('#width'),
readmeLink: $('#readme'),
canvas: $('#canvas'),
canvas2d: $('#customSwitch1'),
fullver: $('#fullver'),
canvas2dver: $('#canvas2dver'),
}
let controller = {
init: function() {
$('[data-toggle="tooltip"]').tooltip();
this.setDefault();
this.bindAllInput();
this.onCanvas2dChange();
this.renderToCanvas();
this.bindDownload();
},
setDefault: function() {
view.textarea.val(model.defaultText);
view.readmeLink.attr('href', model[lang].readme);
view.fontFamilyCustom.attr('placeholder', model[lang].custom_holder.fontFamily);
view.fontWeightCustom.attr('placeholder', model[lang].custom_holder.fontWeight);
view.canvas2d.parent().attr('data-original-title', model[lang].canvas_tips);
if (lang === 'zh') {
view.lang.find('input[value=zh]').attr('checked', true);
// view.wordBreak.find('input[value=break-all]').attr('checked', true);
} else {
view.lang.find('input[value=en]').attr('checked', true);
// view.wordBreak.find('input[value=break-word]').attr('checked', true);
}
},
renderToCanvas: function(text) {
text = text || view.textarea.val();
let is_canvas2d = view.canvas2d[0].checked;
let options = {
canvas2d: is_canvas2d ? document.createElement('canvas').getContext("2d") : null,
lang: view.lang.find('input[checked]').val(),
wordBreak: view.wordBreak.find('input[checked]').val(),
fontWeight: (is_canvas2d && view.fontWeightCustom.val().trim()) || view.fontWeight.find('input[checked]').val(),
fontFamily: (is_canvas2d && view.fontFamilyCustom.val().trim()) || view.fontFamily.find('input[checked]').val(),
fontSize: view.fontSize.val(),
width: view.width.val()
}
is_canvas2d && delete options.lang;
let ctx = view.canvas[0].getContext("2d");
let lines = emojiLineBreak(text, options);
let baseH = 24 * Math.abs((view.fontSize.val() / 16));
view.canvas.attr('width', options.width);
view.canvas.attr('height', baseH * (lines.length + 0.5));
ctx.save();
ctx.font = `${options.fontWeight} ${parseFloat(options.fontSize) + 'px'} ${options.fontFamily}`;
lines.forEach((item, index) => {
ctx.fillText(item, 0, (index + 1) * baseH);
})
ctx.restore();
console.log('options:', options);
console.log('reslut:', lines);
console.log('********************');
},
bindAllInput: function() {
var that = this;
view.allInput.each(function() {
if ($(this).attr('type') === 'radio') {
$(this).on('change',function(e) {
$(this).parents('.btn-group').find('input').removeAttr('checked');
$(this).attr('checked', true);
if (view.canvas2d[0].checked) {
$(this).parents('.input-group').next().find('.custom-input').val($(this).val());
}
that.renderToCanvas();
});
} else {
$(this).on('input',function() {
that.renderToCanvas();
});
}
})
$.merge(view.fontWeightCustom, view.fontFamilyCustom).on('input',function(e) {
let related = $(this).parents('.input-group').prev();
if ($(this).val().trim()) {
related.find('.btn').removeClass('active');
} else {
related.find('input[checked]').parents('.btn').addClass('active');
}
});
},
bindDownload: function() {
view.fullver.click(function() {
let a = document.createElement('a');
a.href = model.fullver.href;
a.download = model.fullver.name;
a.click();
});
view.canvas2dver.click(function() {
let a = document.createElement('a');
a.href = model.canvas2dver.href;
a.download = model.canvas2dver.name;
a.click();
});
},
onCanvas2dChange: function() {
view.canvas2d.change(function() {
console.log(9999)
let is_canvas2d = view.canvas2d[0].checked;
if (is_canvas2d) {
view.lang.find('.btn').removeClass('active');
view.lang.find('input').attr('disabled', true);
view.lang.find('.btn').attr('data-original-title', model[lang].lang_tips);
$('[data-toggle="tooltip"]').tooltip();
view.lang.parents('.input-group').css('display', 'none');
let related = $.merge(view.fontWeightCustom, view.fontFamilyCustom).parents('.input-group');
related.css('display', 'block');
related.each(function() {
if ($(this).find('input').val()) {
$(this).prev().find('input[checked]').parents('.btn').removeClass('active');
}
});
} else {
view.lang.find('input').attr('disabled', false);
view.lang.find('input[checked]').parents('.btn').addClass('active');
view.lang.find('.btn').removeAttr('data-original-title');
view.lang.parents('.input-group').css('display', 'flex');
let related = $.merge(view.fontWeightCustom, view.fontFamilyCustom).parents('.input-group');
related.css('display', 'none');
related.prev().find('input[checked]').parents('.btn').addClass('active');
}
});
}
}
controller.init();
</script>
</html>