UNPKG

emoji-line-break

Version:
446 lines (402 loc) 21 kB
<!DOCTYPE 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="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</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> </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="../dist/emoji-line-break.min.js"></script> <script type="text/javascript"> "use strict"; 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', } } } 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() { 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>