<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html lang='en' class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/ninivert/pen/BpLKRx?depth=everything&order=popularity&page=38&q=generate&show_forks=false" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css'>
<style class="cp-pen-styles">/*IMPORTS*/
@import "https://fonts.googleapis.com/css?family=Open+Sans:300,400|Roboto:400,400i,500|Lobster:400|Source+Code+Pro:400";
/*MAIN*/
html,
body {
margin: 0px;
padding: 0px;
}
body {
padding: 45px;
}
* {
box-sizing: border-box;
font-family: 'Roboto';
font-weight: 400;
color: dimgrey;
}
/*HEADERS AND TEXT*/
h1,
h2,
h3 {
margin: 15px 0;
font-family: 'Open Sans';
font-weight: 300;
}
h1 {
font-weight: 400;
font-family: 'Lobster';
font-size: 45px;
letter-spacing: 3px;
color: crimson;
border-bottom: 1px dashed crimson;
}
h2 {
font-size: 30px;
letter-spacing: 2px;
}
h3 {
font-size: 25px;
letter-spacing: 1px;
}
p {
margin: 10px 0;
color: dimgrey;
}
span {
color: dimgrey;
}
code {
font-family: 'Source Code Pro';
color: black;
background: #ededed;
padding: 0px 5px 0px 5px;
}
pre {
padding: 5px;
overflow: auto;
background: #ededed;
}
pre code {
padding: 0px;
}
img {
width: auto;
max-width: 100%;
max-height: 500px;
display: block;
margin: 1em auto;
}
/*INPUT METHODS*/
button,
.btn {
padding: 15px;
margin: 0 10px 10px 0;
display: inline-block;
border: 0px solid dimgrey;
background: dimgrey;
color: whitesmoke;
outline: none;
transition: all 0.25s, transform 0.1s;
}
button:hover,
.btn:hover {
background: crimson;
color: whitesmoke;
}
button:active,
.btn:active {
background: crimson;
transform: scale(0.8);
}
input[type='text'], input[type='number'], select {
padding: 15px;
margin: 0 10px 10px 0px;
border: 0px solid dimgrey;
background: dimgrey;
color: whitesmoke;
outline: none;
transition: all 0.25s;
}
input[type='text']:hover, input[type='number']:hover, select:hover {
background: grey;
}
input[type='text']:focus, input[type='number']:focus, select:focus {
background: crimson;
color: whitesmoke;
}
input[type='text']:focus::-webkit-input-placeholder, input[type='number']:focus::-webkit-input-placeholder, select:focus::-webkit-input-placeholder {
color: whitesmoke;
}
input[type='text']:focus::-moz-placeholder, input[type='number']:focus::-moz-placeholder, select:focus::-moz-placeholder {
color: whitesmoke;
}
input[type='text']:focus:-ms-input-placeholder, input[type='number']:focus:-ms-input-placeholder, select:focus:-ms-input-placeholder {
color: whitesmoke;
}
input[type='text']:focus:-moz-placeholder, input[type='number']:focus:-moz-placeholder, select:focus:-moz-placeholder {
color: whitesmoke;
}
a {
box-sizing: border-box;
color: crimson;
text-decoration: none;
font-weight: 500;
}
a:hover {
text-decoration: underline;
}
/*MISC*/
.inline {
display: inline-block;
}
.block {
display: block;
}
.hidden {
display: none;
}
/*SCROLLBAR*/
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-button {
width: 0px;
height: 0px;
}
::-webkit-scrollbar-thumb {
background: crimson;
border-radius: 0px;
}
::-webkit-scrollbar-thumb:hover {
background: #d31339;
}
::-webkit-scrollbar-thumb:active {
box-shadow: inset 0px 0px 5px #67091c;
}
::-webkit-scrollbar-track {
background: lightgrey;
border: 0px none darkgrey;
border-radius: 0px;
box-shadow: inset 0px 0px 5px dimgrey;
}
::-webkit-scrollbar-track:hover {
background: lightgrey;
}
::-webkit-scrollbar-track:active {
box-shadow: inset 0px 0px 8px dimgrey;
}
::-webkit-scrollbar-corner {
background: transparent;
}
/*RANGE*/
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 6px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
-webkit-appearance: none;
margin-top: -6px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #dc143c;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
height: 8px;
}
input[type=range]:focus::-ms-fill-lower {
background: #dc143c;
}
input[type=range]:focus::-ms-fill-upper {
background: #dc143c;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 6px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
-webkit-appearance: none;
margin-top: -6px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #dc143c;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
height: 8px;
}
input[type=range]:focus::-ms-fill-lower {
background: #dc143c;
}
input[type=range]:focus::-ms-fill-upper {
background: #dc143c;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 6px 0;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
-webkit-appearance: none;
margin-top: -6px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #dc143c;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #dc143c;
border-radius: 20.1px;
border: 0px solid #ffffff;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 8px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #dc143c;
border: 0px solid #ffffff;
border-radius: 40.2px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0px #333333, 0px 0px 0px #404040;
height: 20px;
width: 20px;
border-radius: 20px;
background: #696969;
cursor: pointer;
height: 8px;
}
input[type=range]:focus::-ms-fill-lower {
background: #dc143c;
}
input[type=range]:focus::-ms-fill-upper {
background: #dc143c;
}
/*LAYOUT*/
.box {
display: block;
width: 100%;
}
.box::after {
visibility: hidden;
display: block;
font-size: 0;
content: '';
clear: both;
height: 0;
}
.box > div {
display: inline-block;
width: 50%;
overflow: auto;
float: left;
}
.box > div:nth-child(odd) {
padding-right: .5em;
}
.box > div:nth-child(even) {
padding-left: .5em;
}
/*MEDIA*/
@media only screen and (max-width: 720px) {
body {
padding: 15px;
}
.box > div {
display: block;
width: 100%;
padding: 0 0 !important;
float: none;
}
}
.fullwidth {
width: 100%;
max-width: 500px;
max-height: 800px;
}
#imgFile {
display: none;
}
input[type='text'], input[type='range'] {
width: 100%;
}
h3 > i.fa {
margin-right: .2em;
}
</style></head><body>
<h1>Meme Generator</h1>
<div class="box">
<div>
<div id="canvasWrapper">
</div>
</div>
<div>
<h3><i class="fa fa-picture-o fa-fw" aria-hidden="true"></i>Source Image</h3>
<div class="box">
<div>
<p>From URL</p>
<input id="imgURL" class="block" type="text" placeholder="Link to image" />
<a href="http://memeful.com/" target="_blank">Memeful.com</a>
</div>
<div>
<p>From Local Disk</p>
<input id="imgFile" type="file" accept="image/*"/>
<label for="imgFile" class="btn"><i class="fa fa-upload fa-fw"></i></label>
</div>
</div>
<h3><i class="fa fa-commenting-o fa-fw" aria-hidden="true"></i>Meme Text</h3>
<div class="box">
<div>
<p>Top Text</p>
<input id="textTop" type="text" class="block" placeholder="Top text" />
</div>
<div>
<p>Bottom Text</p>
<input id="textBottom" type="text" class="block" placeholder="Bottom text" />
</div>
</div>
<h3><i class="fa fa-text-height fa-fw" aria-hidden="true"></i>Text Size</h3>
<div class="box">
<div>
<p>Top Text: <span id="textSizeTopOut">10</span></p>
<input id="textSizeTop" type="range" min="2" max="50" step="2" />
</div>
<div>
<p>Bottom Text: <span id="textSizeBottomOut">10</span></p>
<input id="textSizeBottom" type="range" min="2" max="50" step="2" />
</div>
</div>
<div class="box">
<div>
<h3><i class="fa fa-eye fa-fw" aria-hidden="true"></i>Preview Size</h3>
<input id="trueSize" type="checkbox"/>
<label for="trueSize"><span>Show true size</span></label>
</div>
<div>
<h3><i class="fa fa-download fa-fw" aria-hidden="true"></i>Export</h3>
<p>If the button doesn't work, right-click the image and save it</p>
<p>If you are one mobile, download the source image and directly upload it</p>
<button id="export">Export!</button>
</div>
</div>
</div>
</div>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script>
<script >// CAN\NVAS.js plugin
// ninivert, december 2016
(function (window, document) {
/**
* CAN\VAS Plugin - Adding line breaks to canvas
* @arg {string} [str=Hello World] - text to be drawn
* @arg {number} [x=0] - top left x coordinate of the text
* @arg {number} [y=textSize] - top left y coordinate of the text
* @arg {number} [w=canvasWidth] - maximum width of drawn text
* @arg {number} [lh=1] - line height
* @arg {number} [method=fill] - text drawing method, if 'none', text will not be rendered
*/
CanvasRenderingContext2D.prototype.drawBreakingText = function (str, x, y, w, lh, method) {
// local variables and defaults
var textSize = parseInt(this.font.replace(/\D/gi, ''));
var textParts = [];
var textPartsNo = 0;
var words = [];
var currLine = '';
var testLine = '';
str = str || '';
x = x || 0;
y = y || 0;
w = w || this.canvas.width;
lh = lh || 1;
method = method || 'fill';
// manual linebreaks
textParts = str.split('\n');
textPartsNo = textParts.length;
// split the words of the parts
for (var i = 0; i < textParts.length; i++) {if (window.CP.shouldStopExecution(1)){break;}
words[i] = textParts[i].split(' ');
}
window.CP.exitedLoop(1);
// now that we have extracted the words
// we reset the textParts
textParts = [];
// calculate recommended line breaks
// split between the words
for (var i = 0; i < textPartsNo; i++) {if (window.CP.shouldStopExecution(3)){break;}
// clear the testline for the next manually broken line
currLine = '';
for (var j = 0; j < words[i].length; j++) {if (window.CP.shouldStopExecution(2)){break;}
testLine = currLine + words[i][j] + ' ';
// check if the testLine is of good width
if (this.measureText(testLine).width > w && j > 0) {
textParts.push(currLine);
currLine = words[i][j] + ' ';
} else {
currLine = testLine;
}
}
window.CP.exitedLoop(2);
// replace is to remove trailing whitespace
textParts.push(currLine);
}
window.CP.exitedLoop(3);
// render the text on the canvas
for (var i = 0; i < textParts.length; i++) {if (window.CP.shouldStopExecution(4)){break;}
if (method === 'fill') {
this.fillText(textParts[i].replace(/((\s*\S+)*)\s*/, '$1'), x, y+(textSize*lh*i));
} else if (method === 'stroke') {
this.strokeText(textParts[i].replace(/((\s*\S+)*)\s*/, '$1'), x, y+(textSize*lh*i));
} else if (method === 'none') {
return {'textParts': textParts, 'textHeight': textSize*lh*textParts.length};
} else {
console.warn('drawBreakingText: ' + method + 'Text() does not exist');
return false;
}
}
window.CP.exitedLoop(4);
return {'textParts': textParts, 'textHeight': textSize*lh*textParts.length};
};
}) (window, document);
var canvas = document.createElement('canvas');
var canvasWrapper = document.getElementById('canvasWrapper');
canvasWrapper.appendChild(canvas);
canvas.width = 500;
canvas.height = 500;
var ctx = canvas.getContext('2d');
var padding = 15;
var textTop = 'i don\'t always make a meme';
var textBottom = 'but when i do, i use ninivert\'s generator';
var textSizeTop = 10;
var textSizeBottom = 10;
var image = document.createElement('img');
image.onload = function (ev) {
// delete and recreate canvas do untaint it
canvas.outerHTML = '';
canvas = document.createElement('canvas');
canvasWrapper.appendChild(canvas);
ctx = canvas.getContext('2d');
document.getElementById('trueSize').click();
document.getElementById('trueSize').click();
draw();
};
document.getElementById('imgURL').oninput = function(ev) {
image.src = this.value;
};
document.getElementById('imgFile').onchange = function(ev) {
var reader = new FileReader();
reader.onload = function(ev) {
image.src = reader.result;
};
reader.readAsDataURL(this.files[0]);
};
document.getElementById('textTop').oninput = function(ev) {
textTop = this.value;
draw();
};
document.getElementById('textBottom').oninput = function(ev) {
textBottom = this.value;
draw();
};
document.getElementById('textSizeTop').oninput = function(ev) {
textSizeTop = parseInt(this.value);
draw();
document.getElementById('textSizeTopOut').innerHTML = this.value;
};
document.getElementById('textSizeBottom').oninput = function(ev) {
textSizeBottom = parseInt(this.value);
draw();
document.getElementById('textSizeBottomOut').innerHTML = this.value;
};
document.getElementById('trueSize').onchange = function(ev) {
if (document.getElementById('trueSize').checked) {
canvas.classList.remove('fullwidth');
} else {
canvas.classList.add('fullwidth');
}
};
document.getElementById('export').onclick = function () {
var img = canvas.toDataURL('image/png');
var link = document.createElement("a");
link.download = 'My Meme';
link.href = img;
link.click();
var win = window.open('', '_blank');
win.document.write('<img style="box-shadow: 0 0 1em 0 dimgrey;" src="' + img + '"/>');
win.document.write('<h1 style="font-family: Helvetica; font-weight: 300">Right Click > Save As<h1>');
win.document.body.style.padding = '1em';
};
function style(font, size, align, base) {
ctx.font = size + 'px ' + font;
ctx.textAlign = align;
ctx.textBaseline = base;
}
function draw() {
// uppercase the text
var top = textTop.toUpperCase();
var bottom = textBottom.toUpperCase();
// set appropriate canvas size
canvas.width = image.width;
canvas.height = image.height;
// draw the image
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
// styles
ctx.fillStyle = '#fff';
ctx.strokeStyle = '#000';
ctx.lineWidth = canvas.width*0.004;
var _textSizeTop = textSizeTop/100*canvas.width;
var _textSizeBottom = textSizeBottom/100*canvas.width;
// draw top text
style('Impact', _textSizeTop, 'center', 'bottom');
ctx.drawBreakingText(top, canvas.width/2, _textSizeTop+padding, null, 1, 'fill');
ctx.drawBreakingText(top, canvas.width/2, _textSizeTop+padding, null, 1, 'stroke');
// draw bottom text
style('Impact', _textSizeBottom, 'center', 'top');
var height = ctx.drawBreakingText(bottom, 0, 0, null, 1, 'none').textHeight;
console.log(ctx.drawBreakingText(bottom, 0, 0, null, 1, 'none'));
ctx.drawBreakingText(bottom, canvas.width/2, canvas.height-padding-height, null, 1, 'fill');
ctx.drawBreakingText(bottom, canvas.width/2, canvas.height-padding-height, null, 1, 'stroke');
}
image.src = 'https://imgflip.com/s/meme/The-Most-Interesting-Man-In-The-World.jpg';
document.getElementById('textSizeTop').value = textSizeTop;
document.getElementById('textSizeBottom').value = textSizeBottom;
document.getElementById('textSizeTopOut').innerHTML = textSizeTop;
document.getElementById('textSizeBottomOut').innerHTML = textSizeBottom;
//# sourceURL=pen.js
</script>
</body></html>