-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.html
225 lines (209 loc) · 43.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<!doctype html>
<html lang='en-us'>
<head>
<title>Mercator Studio</title>
<link rel='shortcut icon' type='image/png' href='icon.png'>
<meta charset='utf-8'>
<meta name='author' content='Xing'>
<meta name='description' content='A camera-feed-editing extension for Google Meet'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<meta property='og:title' content='Mercator Studio'>
<meta property='og:type' content='website'>
<meta property='og:url' content='https://x-ing.space/mercator'>
<meta property='og:description' content='A camera-feed-editing extension for Google Meet'>
<meta property='og:image' content='https://x-ing.space/mercator/src/icon.png'>
<style>
html {
margin: 0;
background: #eee;
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif
}
body {
margin: 0;
}
*{
box-sizing: border-box;
}
main{
margin-right: 1rem;
margin-left: auto;
width: 64ch;
max-width: calc(100vw - 2rem);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
right: 0
}
main>*{
font-weight: normal ;
width: inherit;
max-width: inherit;
margin-bottom: 1rem;
line-height: 1.4rem;
}
h1 {
margin-bottom: .4rem;
}
h2 {
margin-bottom: 2.5rem;
}
#install{
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1rem;
}
a,button{
flex-grow: 1;
border-radius: 1ch;
border: .15rem solid #aaa;
font-family: inherit;
font-size: 1.2rem;
color: black;
text-decoration: none;
padding: 1rem;
text-align: center;
transition: background 200ms;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
a:focus,button:focus{
outline: 0;
border-color: black;
}
#install>a>svg{
margin-bottom: .5rem;
}
a:hover,button:hover{
background: white
}
#bookmarklet::after{
content: 'Bookmarklet'
}
video{
background: #ccc;
border-radius: 1rem;
width: 100%;
height: auto;
display: none;
}
#readme{
text-align: left;
white-space: pre-wrap;
padding: 0 1rem;
}
</style>
</head>
<body>
<main>
<svg width='128' height='128' viewBox='0 0 128 128' xmlns='http://www.w3.org/2000/svg'>
<title>Logo of Mercator Studio for Google Meet</title>
<desc>A white video recorder icon in a dark teal circle, wrapped by stripes in shades of pastel orange.</desc>
<circle cx='64' cy='64' r='64' fill='hsl(31, 100%, 73%)'/>
<rect fill='hsl( 18, 100%, 68%)' width='96' x='16' y='0' height='128'/>
<rect fill='hsl(-10, 100%, 80%)' width='80' x='16' y='0' height='128'/>
<rect fill='hsl( 5, 90%, 72%)' width='64' x='16' y='0' height='128'/>
<rect fill='hsl( 48, 100%, 75%)' width='48' x='16' y='0' height='128'/>
<rect fill='hsl( 36, 100%, 70%)' width='32' x='16' y='0' height='128'/>
<rect fill='hsl( 20, 90%, 70%)' width='16' x='16' y='0' height='128'/>
<circle cx='64' cy='64' r='52' fill='hsl(191, 35%, 41%)'/>
<rect x='34' y='46' width='44' height='36' fill='white' rx='8' ry='8'/>
<path d='M68 64l22 -10v20z' fill='white' stroke-width='8' stroke='white' stroke-linejoin='round'/>
<desc>(C) Xing Liu, 2020</desc>
</svg>
<h1>Mercator Studio for Google Meet</h1>
<h2>A project by Xing</h2>
<section id='install'>
<a href='https://chrome.google.com/webstore/detail/ohcmmfphdpigpccfppacepjhamgcffjh'>
<svg height='32' viewBox="1 1 176 176"><style>.B{clip-path:url(#C)}.C{fill:#3e2723}.D{fill-opacity:.15}.E{fill-opacity:.2}</style><defs><circle id="A" cx="96" cy="96" r="88"/><path id="B" d="M8 184h83.77l38.88-38.88V116h-69.3L8 24.48z"/></defs><clipPath id="C"><use xlink:href="#A"/></clipPath><g class="B" transform="translate(-7 -7)"><path d="M21.97 8v108h39.4L96 56h88V8z" fill="#db4437"/><linearGradient id="D" x1="29.34" x2="81.84" y1="75.02" y2="44.35" gradientUnits="userSpaceOnUse"><stop stop-color="#a52714" stop-opacity=".6" offset="0"/><stop stop-color="#a52714" stop-opacity="0" offset=".66"/></linearGradient><path d="M21.97 8v108h39.4L96 56h88V8z" fill="url(#D)"/><path d="M62.3 115.6L22.48 47.3l-.58 1 39.54 67.8z" class="C D"/><use xlink:href="#B" fill="#0f9d58"/><linearGradient id="E" x1="110.9" x2="52.54" y1="164.5" y2="130.3" gradientUnits="userSpaceOnUse"><stop stop-color="#055524" stop-opacity=".4" offset="0"/><stop stop-color="#055524" stop-opacity="0" offset=".33"/></linearGradient><path d="M8 184h83.77l38.88-38.88V116h-69.3L8 24.48z" fill="url(#E)"/><path d="M129.8 117.3l-.83-.48-38.4 67.15h1.15l38.1-66.64z" fill="#263238" class="D"/><defs><path id="F" d="M8 184h83.77l38.88-38.88V116h-69.3L8 24.48z"/></defs><clipPath id="G"><use xlink:href="#F"/></clipPath><g clip-path="url(#G)"><path d="M96 56l34.65 60-38.88 68H184V56z" fill="#ffcd40"/><linearGradient id="H" x1="121.9" x2="136.6" y1="49.8" y2="114.1" gradientUnits="userSpaceOnUse"><stop stop-color="#ea6100" stop-opacity=".3" offset="0"/><stop stop-color="#ea6100" stop-opacity="0" offset=".66"/></linearGradient><path d="M96 56l34.65 60-38.88 68H184V56z" fill="url(#H)"/></g><path d="M96 56l34.65 60-38.88 68H184V56z" fill="#ffcd40"/><path d="M96 56l34.65 60-38.88 68H184V56z" fill="url(#H)"/><defs><path id="I" d="M96 56l34.65 60-38.88 68H184V56z"/></defs><clipPath id="J"><use xlink:href="#I"/></clipPath><g clip-path="url(#J)"><path d="M21.97 8v108h39.4L96 56h88V8z" fill="#db4437"/><path d="M21.97 8v108h39.4L96 56h88V8z" fill="url(#D)"/></g></g><radialGradient id="K" cx="668.2" cy="55.95" r="84.08" gradientTransform="translate(-576)" gradientUnits="userSpaceOnUse"><stop stop-color="#3e2723" stop-opacity=".2" offset="0"/><stop stop-color="#3e2723" stop-opacity="0" offset="1"/></radialGradient><g transform="translate(-7 -7)"><path d="M96 56v20.95L174.4 56z" fill="url(#K)" class="B"/><g class="B"><defs><path id="L" d="M21.97 8v40.34L61.36 116 96 56h88V8z"/></defs><clipPath id="M"><use xlink:href="#L"/></clipPath><g clip-path="url(#M)"><use xlink:href="#B" fill="#0f9d58"/><path d="M8 184h83.77l38.88-38.88V116h-69.3L8 24.48z" fill="url(#E)"/></g></g></g><radialGradient id="N" cx="597.9" cy="48.52" r="78.04" gradientTransform="translate(-576)" gradientUnits="userSpaceOnUse"><stop stop-color="#3e2723" stop-opacity=".2" offset="0"/><stop stop-color="#3e2723" stop-opacity="0" offset="1"/></radialGradient><path transform="translate(-7 -7)" d="M21.97 48.45l57.25 57.24L61.36 116z" fill="url(#N)" class="B"/><radialGradient id="O" cx="671.8" cy="96.14" r="87.87" gradientTransform="translate(-576)" gradientUnits="userSpaceOnUse"><stop stop-color="#263238" stop-opacity=".2" offset="0"/><stop stop-color="#263238" stop-opacity="0" offset="1"/></radialGradient><g transform="translate(-7 -7)"><path d="M91.83 183.9l20.96-78.2 17.86 10.3z" fill="url(#O)" class="B"/><g class="B"><circle cx="96" cy="96" r="40" fill="#f1f1f1"/><circle cx="96" cy="96" r="32" fill="#4285f4"/><path d="M96 55c-22.1 0-40 17.9-40 40v1c0-22.1 17.9-40 40-40h88v-1H96z" class="C E"/><path d="M130.6 116c-6.92 11.94-19.8 20-34.6 20-14.8 0-27.7-8.06-34.6-20h-.04L8 24.48v1L61.4 117c6.92 11.94 19.8 20 34.6 20 14.8 0 27.68-8.05 34.6-20h.05v-1h-.06z" fill="#fff" fill-opacity=".1"/><path d="M97 56c-.17 0-.33.02-.5.03C118.36 56.3 136 74.08 136 96s-17.64 39.7-39.5 39.97c.17 0 .33.03.5.03 22.1 0 40-17.9 40-40s-17.9-40-40-40z" opacity=".1" class="C"/><path d="M131 117.3c3.4-5.88 5.37-12.68 5.37-19.96a39.87 39.87 0 0 0-1.87-12.09c.95 3.42 1.5 7 1.5 10.73 0 7.28-1.97 14.08-5.37 19.96l.02.04-38.88 68h1.16L131 117.3z" fill="#fff" class="E"/><path d="M96 9c48.43 0 87.72 39.13 88 87.5 0-.17.01-.33.01-.5 0-48.6-39.4-88-88-88S8 47.4 8 96c0 .17.01.33.01.5C8.28 48.13 47.57 9 96 9z" fill="#fff" class="E"/><path d="M96 183c48.43 0 87.72-39.13 88-87.5 0 .17.01.33.01.5 0 48.6-39.4 88-88 88S8 144.6 8 96c0-.17.01-.33.01-.5.27 48.37 39.56 87.5 88 87.5z" class="C D"/></g></g></svg>
Chrome Web Store
</a>
<a href='https://addons.mozilla.org/en-US/firefox/addon/mercator-studio/'>
<svg height='32' viewBox="0 0 87.418564 81.96698"> <defs id="defs978"> <linearGradient gradientTransform="translate(3.7,-0.0040855)" gradientUnits="userSpaceOnUse" y2="74.468002" x2="6.447" y1="12.393" x1="70.786003" id="a"> <stop id="stop834" stop-color="#fff44f" offset=".048" /> <stop id="stop836" stop-color="#ffe847" offset=".111" /> <stop id="stop838" stop-color="#ffc830" offset=".225" /> <stop id="stop840" stop-color="#ff980e" offset=".368" /> <stop id="stop842" stop-color="#ff8b16" offset=".401" /> <stop id="stop844" stop-color="#ff672a" offset=".462" /> <stop id="stop846" stop-color="#ff3647" offset=".534" /> <stop id="stop848" stop-color="#e31587" offset=".705" /> </linearGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="80.796997" cy="-8515.1211" cx="-7907.187" id="b"> <stop id="stop851" stop-color="#ffbd4f" offset=".129" /> <stop id="stop853" stop-color="#ffac31" offset=".186" /> <stop id="stop855" stop-color="#ff9d17" offset=".247" /> <stop id="stop857" stop-color="#ff980e" offset=".283" /> <stop id="stop859" stop-color="#ff563b" offset=".403" /> <stop id="stop861" stop-color="#ff3750" offset=".467" /> <stop id="stop863" stop-color="#f5156c" offset=".71" /> <stop id="stop865" stop-color="#eb0878" offset=".782" /> <stop id="stop867" stop-color="#e50080" offset=".86" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="80.796997" cy="-8482.0889" cx="-7936.7109" id="c"> <stop id="stop870" stop-color="#960e18" offset=".3" /> <stop id="stop872" stop-opacity=".74" stop-color="#b11927" offset=".351" /> <stop id="stop874" stop-opacity=".343" stop-color="#db293d" offset=".435" /> <stop id="stop876" stop-opacity=".094" stop-color="#f5334b" offset=".497" /> <stop id="stop878" stop-opacity="0" stop-color="#ff3750" offset=".53" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="58.534" cy="-8533.457" cx="-7926.9702" id="d"> <stop id="stop881" stop-color="#fff44f" offset=".132" /> <stop id="stop883" stop-color="#ffdc3e" offset=".252" /> <stop id="stop885" stop-color="#ff9d12" offset=".506" /> <stop id="stop887" stop-color="#ff980e" offset=".526" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="38.471001" cy="-8460.9844" cx="-7945.6479" id="e"> <stop id="stop890" stop-color="#3a8ee6" offset=".353" /> <stop id="stop892" stop-color="#5c79f0" offset=".472" /> <stop id="stop894" stop-color="#9059ff" offset=".669" /> <stop id="stop896" stop-color="#c139e6" offset="1" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.972,-0.235,0.275,1.138,10095.002,7833.7939)" r="20.396999" cy="-8491.5459" cx="-7935.6201" id="f"> <stop id="stop899" stop-opacity="0" stop-color="#9059ff" offset=".206" /> <stop id="stop901" stop-opacity=".064" stop-color="#8c4ff3" offset=".278" /> <stop id="stop903" stop-opacity=".45" stop-color="#7716a8" offset=".747" /> <stop id="stop905" stop-opacity=".6" stop-color="#6e008b" offset=".975" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="27.676001" cy="-8518.4268" cx="-7937.731" id="g"> <stop id="stop908" stop-color="#ffe226" offset="0" /> <stop id="stop910" stop-color="#ffdb27" offset=".121" /> <stop id="stop912" stop-color="#ffc82a" offset=".295" /> <stop id="stop914" stop-color="#ffa930" offset=".502" /> <stop id="stop916" stop-color="#ff7e37" offset=".732" /> <stop id="stop918" stop-color="#ff7139" offset=".792" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="118.081" cy="-8535.9814" cx="-7915.9771" id="h"> <stop id="stop921" stop-color="#fff44f" offset=".113" /> <stop id="stop923" stop-color="#ff980e" offset=".456" /> <stop id="stop925" stop-color="#ff5634" offset=".622" /> <stop id="stop927" stop-color="#ff3647" offset=".716" /> <stop id="stop929" stop-color="#e31587" offset=".904" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.105,0.995,-0.653,0.069,-4680.304,8470.1869)" r="86.499001" cy="-8522.8594" cx="-7927.165" id="i"> <stop id="stop932" stop-color="#fff44f" offset="0" /> <stop id="stop934" stop-color="#ffe847" offset=".06" /> <stop id="stop936" stop-color="#ffc830" offset=".168" /> <stop id="stop938" stop-color="#ff980e" offset=".304" /> <stop id="stop940" stop-color="#ff8b16" offset=".356" /> <stop id="stop942" stop-color="#ff672a" offset=".455" /> <stop id="stop944" stop-color="#ff3647" offset=".57" /> <stop id="stop946" stop-color="#e31587" offset=".737" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="73.720001" cy="-8508.1758" cx="-7938.3828" id="j"> <stop id="stop949" stop-color="#fff44f" offset=".137" /> <stop id="stop951" stop-color="#ff980e" offset=".48" /> <stop id="stop953" stop-color="#ff5634" offset=".592" /> <stop id="stop955" stop-color="#ff3647" offset=".655" /> <stop id="stop957" stop-color="#e31587" offset=".904" /> </radialGradient> <radialGradient gradientUnits="userSpaceOnUse" gradientTransform="translate(7978.7,8523.9959)" r="80.685997" cy="-8503.8613" cx="-7918.9229" id="k"> <stop id="stop960" stop-color="#fff44f" offset=".094" /> <stop id="stop962" stop-color="#ffe141" offset=".231" /> <stop id="stop964" stop-color="#ffaf1e" offset=".509" /> <stop id="stop966" stop-color="#ff980e" offset=".626" /> </radialGradient> <linearGradient gradientTransform="translate(3.7,-0.0040855)" gradientUnits="userSpaceOnUse" y2="66.806" x2="15.267" y1="12.061" x1="70.013" id="l"> <stop id="stop969" stop-opacity=".8" stop-color="#fff44f" offset=".167" /> <stop id="stop971" stop-opacity=".634" stop-color="#fff44f" offset=".266" /> <stop id="stop973" stop-opacity=".217" stop-color="#fff44f" offset=".489" /> <stop id="stop975" stop-opacity="0" stop-color="#fff44f" offset=".6" /> </linearGradient> </defs> <path style="fill:url(#a)" id="path980" d="m 79.616,26.826915 c -1.684,-4.052 -5.1,-8.427 -7.775,-9.81 a 40.266,40.266 0 0 1 3.925,11.764 l 0.007,0.065 c -4.382,-10.925 -11.813,-15.33 -17.882,-24.9220005 -0.307,-0.485 -0.614,-0.971 -0.913,-1.484 -0.171,-0.293 -0.308,-0.557 -0.427,-0.8 a 7.053,7.053 0 0 1 -0.578,-1.535 0.1,0.1 0 0 0 -0.088,-0.1 0.138,0.138 0 0 0 -0.073,0 c -0.005,0 -0.013,0.009 -0.019,0.011 -0.006,0.002 -0.019,0.011 -0.028,0.015 l 0.015,-0.026 c -9.735,5.7 -13.038,16.2520005 -13.342,21.5300005 a 19.387,19.387 0 0 0 -10.666,4.111 11.587,11.587 0 0 0 -1,-0.758 17.968,17.968 0 0 1 -0.109,-9.473 28.705,28.705 0 0 0 -9.329,7.21 h -0.018 c -1.536,-1.947 -1.428,-8.367 -1.34,-9.708 a 6.928,6.928 0 0 0 -1.294,0.687 28.225,28.225 0 0 0 -3.788,3.245 33.845,33.845 0 0 0 -3.623,4.347 v 0.006 -0.007 a 32.733,32.733 0 0 0 -5.2,11.743 l -0.052,0.256 c -0.073,0.341 -0.336,2.049 -0.381,2.42 0,0.029 -0.006,0.056 -0.009,0.085 A 36.937,36.937 0 0 0 5,41.041915 v 0.2 a 38.759,38.759 0 0 0 76.954,6.554 c 0.065,-0.5 0.118,-0.995 0.176,-1.5 a 39.857,39.857 0 0 0 -2.514,-19.469 z m -44.67,30.338 c 0.181,0.087 0.351,0.181 0.537,0.264 l 0.027,0.017 q -0.282,-0.135 -0.564,-0.281 z m 8.878,-23.376 z m 31.952,-4.934 v -0.037 l 0.007,0.041 z" /> <path style="fill:url(#b)" id="path982" d="m 79.616,26.826915 c -1.684,-4.052 -5.1,-8.427 -7.775,-9.81 a 40.266,40.266 0 0 1 3.925,11.764 v 0.037 l 0.007,0.041 a 35.1,35.1 0 0 1 -1.206,26.158 c -4.442,9.531 -15.194,19.3 -32.024,18.825 -18.185,-0.515 -34.2,-14.009 -37.194,-31.683 -0.545,-2.787 0,-4.2 0.274,-6.465 A 28.876,28.876 0 0 0 5,41.041915 v 0.2 a 38.759,38.759 0 0 0 76.954,6.554 c 0.065,-0.5 0.118,-0.995 0.176,-1.5 a 39.857,39.857 0 0 0 -2.514,-19.469 z" /> <path style="fill:url(#c)" id="path984" d="m 79.616,26.826915 c -1.684,-4.052 -5.1,-8.427 -7.775,-9.81 a 40.266,40.266 0 0 1 3.925,11.764 v 0.037 l 0.007,0.041 a 35.1,35.1 0 0 1 -1.206,26.158 c -4.442,9.531 -15.194,19.3 -32.024,18.825 -18.185,-0.515 -34.2,-14.009 -37.194,-31.683 -0.545,-2.787 0,-4.2 0.274,-6.465 A 28.876,28.876 0 0 0 5,41.041915 v 0.2 a 38.759,38.759 0 0 0 76.954,6.554 c 0.065,-0.5 0.118,-0.995 0.176,-1.5 a 39.857,39.857 0 0 0 -2.514,-19.469 z" /> <path style="fill:url(#d)" id="path986" d="m 60.782,31.382915 c 0.084,0.059 0.162,0.118 0.241,0.177 a 21.1,21.1 0 0 0 -3.6,-4.695 C 45.377,14.816915 54.266,0.7419145 55.765,0.0269145 l 0.015,-0.022 c -9.735,5.7 -13.038,16.2520005 -13.342,21.5300005 0.452,-0.031 0.9,-0.069 1.362,-0.069 a 19.56,19.56 0 0 1 16.982,9.917 z" /> <path style="fill:url(#e)" id="path988" d="m 43.825,33.788915 c -0.064,0.964 -3.47,4.289 -4.661,4.289 -11.021,0 -12.81,6.667 -12.81,6.667 0.488,5.614 4.4,10.238 9.129,12.684 0.216,0.112 0.435,0.213 0.654,0.312 q 0.569,0.252 1.138,0.466 a 17.235,17.235 0 0 0 5.043,0.973 c 19.317,0.906 23.059,-23.1 9.119,-30.066 a 13.38,13.38 0 0 1 9.345,2.269 19.56,19.56 0 0 0 -16.982,-9.917 c -0.46,0 -0.91,0.038 -1.362,0.069 a 19.387,19.387 0 0 0 -10.666,4.111 c 0.591,0.5 1.258,1.168 2.663,2.553 2.63,2.591 9.375,5.275 9.39,5.59 z" /> <path style="fill:url(#f)" id="path990" d="m 43.825,33.788915 c -0.064,0.964 -3.47,4.289 -4.661,4.289 -11.021,0 -12.81,6.667 -12.81,6.667 0.488,5.614 4.4,10.238 9.129,12.684 0.216,0.112 0.435,0.213 0.654,0.312 q 0.569,0.252 1.138,0.466 a 17.235,17.235 0 0 0 5.043,0.973 c 19.317,0.906 23.059,-23.1 9.119,-30.066 a 13.38,13.38 0 0 1 9.345,2.269 19.56,19.56 0 0 0 -16.982,-9.917 c -0.46,0 -0.91,0.038 -1.362,0.069 a 19.387,19.387 0 0 0 -10.666,4.111 c 0.591,0.5 1.258,1.168 2.663,2.553 2.63,2.591 9.375,5.275 9.39,5.59 z" /> <path style="fill:url(#g)" id="path992" d="m 29.965,24.356915 c 0.314,0.2 0.573,0.374 0.8,0.531 a 17.968,17.968 0 0 1 -0.109,-9.473 28.705,28.705 0 0 0 -9.329,7.21 c 0.189,-0.005 5.811,-0.106 8.638,1.732 z" /> <path style="fill:url(#h)" id="path994" d="m 5.354,42.158915 c 2.991,17.674 19.009,31.168 37.194,31.683 16.83,0.476 27.582,-9.294 32.024,-18.825 a 35.1,35.1 0 0 0 1.206,-26.158 v -0.037 c 0,-0.029 -0.006,-0.046 0,-0.037 l 0.007,0.065 c 1.375,8.977 -3.191,17.674 -10.329,23.555 l -0.022,0.05 c -13.908,11.327 -27.218,6.834 -29.912,5 q -0.282,-0.135 -0.564,-0.281 c -8.109,-3.876 -11.459,-11.264 -10.741,-17.6 a 9.953,9.953 0 0 1 -9.181,-5.775 14.618,14.618 0 0 1 14.249,-0.572 19.3,19.3 0 0 0 14.552,0.572 c -0.015,-0.315 -6.76,-3 -9.39,-5.59 -1.405,-1.385 -2.072,-2.052 -2.663,-2.553 a 11.587,11.587 0 0 0 -1,-0.758 c -0.23,-0.157 -0.489,-0.327 -0.8,-0.531 -2.827,-1.838 -8.449,-1.737 -8.635,-1.732 h -0.018 c -1.536,-1.947 -1.428,-8.367 -1.34,-9.708 a 6.928,6.928 0 0 0 -1.294,0.687 28.225,28.225 0 0 0 -3.788,3.245 33.845,33.845 0 0 0 -3.638,4.337 v 0.006 -0.007 a 32.733,32.733 0 0 0 -5.2,11.743 c -0.019,0.079 -1.396,6.099 -0.717,9.221 z" /> <path style="fill:url(#i)" id="path996" d="m 57.425,26.864915 a 21.1,21.1 0 0 1 3.6,4.7 c 0.213,0.161 0.412,0.321 0.581,0.476 8.787,8.1 4.183,19.55 3.84,20.365 7.138,-5.881 11.7,-14.578 10.329,-23.555 -4.384,-10.93 -11.815,-15.335 -17.884,-24.9270005 -0.307,-0.485 -0.614,-0.971 -0.913,-1.484 -0.171,-0.293 -0.308,-0.557 -0.427,-0.8 a 7.053,7.053 0 0 1 -0.578,-1.535 0.1,0.1 0 0 0 -0.088,-0.1 0.138,0.138 0 0 0 -0.073,0 c -0.005,0 -0.013,0.009 -0.019,0.011 -0.006,0.002 -0.019,0.011 -0.028,0.015 -1.499,0.711 -10.388,14.7860005 1.66,26.8340005 z" /> <path style="fill:url(#j)" id="path998" d="m 61.6,32.035915 c -0.169,-0.155 -0.368,-0.315 -0.581,-0.476 -0.079,-0.059 -0.157,-0.118 -0.241,-0.177 a 13.38,13.38 0 0 0 -9.345,-2.269 c 13.94,6.97 10.2,30.972 -9.119,30.066 a 17.235,17.235 0 0 1 -5.043,-0.973 q -0.569,-0.213 -1.138,-0.466 c -0.219,-0.1 -0.438,-0.2 -0.654,-0.312 l 0.027,0.017 c 2.694,1.839 16,6.332 29.912,-5 l 0.022,-0.05 c 0.347,-0.81 4.951,-12.263 -3.84,-20.36 z" /> <path style="fill:url(#k)" id="path1000" d="m 26.354,44.744915 c 0,0 1.789,-6.667 12.81,-6.667 1.191,0 4.6,-3.325 4.661,-4.289 a 19.3,19.3 0 0 1 -14.552,-0.572 14.618,14.618 0 0 0 -14.249,0.572 9.953,9.953 0 0 0 9.181,5.775 c -0.718,6.337 2.632,13.725 10.741,17.6 0.181,0.087 0.351,0.181 0.537,0.264 -4.733,-2.445 -8.641,-7.069 -9.129,-12.683 z" /> <path style="fill:url(#l)" id="path1002" d="m 79.616,26.826915 c -1.684,-4.052 -5.1,-8.427 -7.775,-9.81 a 40.266,40.266 0 0 1 3.925,11.764 l 0.007,0.065 c -4.382,-10.925 -11.813,-15.33 -17.882,-24.9220005 -0.307,-0.485 -0.614,-0.971 -0.913,-1.484 -0.171,-0.293 -0.308,-0.557 -0.427,-0.8 a 7.053,7.053 0 0 1 -0.578,-1.535 0.1,0.1 0 0 0 -0.088,-0.1 0.138,0.138 0 0 0 -0.073,0 c -0.005,0 -0.013,0.009 -0.019,0.011 -0.006,0.002 -0.019,0.011 -0.028,0.015 l 0.015,-0.026 c -9.735,5.7 -13.038,16.2520005 -13.342,21.5300005 0.452,-0.031 0.9,-0.069 1.362,-0.069 a 19.56,19.56 0 0 1 16.982,9.917 13.38,13.38 0 0 0 -9.345,-2.269 c 13.94,6.97 10.2,30.972 -9.119,30.066 a 17.235,17.235 0 0 1 -5.043,-0.973 q -0.569,-0.213 -1.138,-0.466 c -0.219,-0.1 -0.438,-0.2 -0.654,-0.312 l 0.027,0.017 q -0.282,-0.135 -0.564,-0.281 c 0.181,0.087 0.351,0.181 0.537,0.264 -4.733,-2.446 -8.641,-7.07 -9.129,-12.684 0,0 1.789,-6.667 12.81,-6.667 1.191,0 4.6,-3.325 4.661,-4.289 -0.015,-0.315 -6.76,-3 -9.39,-5.59 -1.405,-1.385 -2.072,-2.052 -2.663,-2.553 a 11.587,11.587 0 0 0 -1,-0.758 17.968,17.968 0 0 1 -0.109,-9.473 28.705,28.705 0 0 0 -9.329,7.21 h -0.018 c -1.536,-1.947 -1.428,-8.367 -1.34,-9.708 a 6.928,6.928 0 0 0 -1.294,0.687 28.225,28.225 0 0 0 -3.788,3.245 33.845,33.845 0 0 0 -3.623,4.347 v 0.006 -0.007 a 32.733,32.733 0 0 0 -5.2,11.743 l -0.052,0.256 c -0.073,0.341 -0.4,2.073 -0.447,2.445 0,0.028 0,-0.029 0,0 A 45.094,45.094 0 0 0 5,41.041915 v 0.2 a 38.759,38.759 0 0 0 76.954,6.554 c 0.065,-0.5 0.118,-0.995 0.176,-1.5 a 39.857,39.857 0 0 0 -2.514,-19.469 z m -3.845,1.991 0.007,0.041 z" /> </svg>
Firefox Addons
</a>
<a href='https://greasyfork.org/en/scripts/406944'>
<svg height='32' viewBox="0 0 96 96"> <circle fill="#000" r="48" cy="48" cx="48"/> <g id="text-group"><path fill="#fff" d=" M10 5h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18 M10 25h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18 M10 45h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18 M10 65h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18 M10 85h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18m10 0h2v18h-2v-18 "/></g> <g id="fork-group"><path fill="#000" d="M20 16l62 62l-8 8l-62-62z"/><path fill="#fff" d="M18 18l60 60l-4 4l-60-60z"/></g> </svg>
Greasyfork Scripts
</a>
<a id='bookmarklet' href='javascript:(async function(){"use strict";const t=document.createElement("aside");t.style.position="absolute",t.style.zIndex=10,t.style.pointerEvents="none";const e=t.attachShadow({mode:"open"}),n=navigator.userAgent.includes("Firefox"),i=document.createElement("main"),r=document.createElement("style"),a="Roboto, RobotDraft, Helvetica, sans-serif, serif",s=`"Google Sans", `+a;r.textContent=`\na, button {\n\tall: unset;\n\tcursor: pointer;\n\ttext-align: center;\n}\nmain, main * {\n\tbox-sizing: border-box;\n\ttransition-duration: 200ms;\n\ttransition-property: opacity, background, transform, padding, border-radius, border-color;\n\tcolor: inherit;\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tfont-weight: inherit;\n}\n@media (prefers-reduced-motion) {\n\tmain, main * {\n\t\ttransition-duration: 0s;\n\t}\n}\n:not(input) {\n\tuser-select: none;\n}\n:focus {\n\toutline: 0;\n}\n\n/* -- */\n\nmain {\n\t--bg: #3C4042;\n\t--bg-x: #434649;\n\t--bg-xx: #505457;\n\t--txt: white;\t\n\n\tfont-family: ${s};\n\tfont-size: 0.9rem;\n\twidth: 25rem;\n\tmax-width: 100vw;\n\theight: 100vh;\n\tposition: fixed;\n\tbottom: 0;\n\tleft: 0;\n\tpadding: 0.5rem;\n\tdisplay: flex;\n\tflex-direction: column-reverse;\n\toverflow: hidden;\n\tpointer-events: none;\n\tcolor: var(--txt);\n}\n#fields,\n#bar,\n#labels > * {\n\tborder-radius: .5rem;\n\tbox-shadow: 0 .1rem .25rem #0004;\n\tpointer-events: all;\n}\n:not(.edit) > #fields {\n\tdisplay: none;\n}\n:not(.edit) > #bar{\n\tborder-radius: 1.5rem;\n\tflex-basis: 4rem;\n}\n#text:hover, #text:focus,\n#presets:hover,\n#bar > :hover, #bar > :focus,\n#tips > * {\n\tbackground: var(--bg-x);\n}\n#text:hover:focus,\n#presets:hover,\n#bar > :hover:focus {\n\tbackground: var(--bg-xx);\n}\n\n/* -- */\n\n#tips {\n\tposition: relative;\n\tfont-family: ${a};\n\tfont-size: 0.8rem;\n\tline-height: 1rem;\n\tz-index: 10;\n}\n#tips > * {\n\tdisplay: block;\n\tposition: absolute;\n\tbottom: 0rem;\n\theight: 1.5rem;\n\tpadding: 0.25rem;\n\tborder-radius: 0.25rem;\n}\n#tips > :not(.show) {\n\topacity: 0;\n}\n#tips > [for=minimize] {\n\tleft: 0;\n}\n#tips > [for=previews] {\n\tleft: 50%;\n\ttransform: translateX(-50%);\n}\n#tips > [for=donate] {\n\tright: 0;\n}\n.edit > #tips > * {\n\ttop: 1rem;\n}\n\n/* -- */\n\n#bar {\n\tmargin-top: 0.5rem;\n\toverflow: hidden;\n\tflex: 0 0 auto;\n\tdisplay: flex;\n}\n.minimize > #bar {\n\twidth: 1rem;\n}\n#bar > * {\n\tbackground: var(--bg);\n}\n#bar > :not(#previews) {\n\tfont-size: 0.5rem;\n\tflex: 0 0 1.5rem;\n\twidth: var(--radius);\n\ttext-align: center;\n\tline-height: 4rem;\n\theight: 100%;\n\toverflow-wrap: anywhere;\n}\n.edit > #bar > :not(#previews),\n.edit > #bar > #previews > h2,\n.minimize #bar :not(#minimize) {\n\tdisplay: none;\n}\n:not(.minimize) > #bar > #minimize:hover {\n\tpadding-right: 2px;\n}\n.minimize > #bar:hover > #minimize,\n#donate:hover {\n\tpadding-left: 2px;\n}\n.minimize > #bar > #minimize{\n\tflex-basis: 1rem;\n}\n#previews {\n\tflex: 1 0 0;\n\twidth: 0;\n\tdisplay: flex;\n}\n#previews > :not(h2) {\n\twidth: auto;\n\theight: auto;\n\tbackground-image: linear-gradient(90deg,\n\t\thsl( 18, 100%, 68%) 16.7%,\thsl(-10, 100%, 80%) 16.7%,\n\t\thsl(-10, 100%, 80%) 33.3%,\thsl(5,90%, 72%) 33.3%,\n\t\thsl(5,90%, 72%) 50%,\thsl( 48, 100%, 75%) 50%,\n\t\thsl( 48, 100%, 75%) 66.7%,\thsl( 36, 100%, 70%) 66.7%,\n\t\thsl( 36, 100%, 70%) 83.3%,\thsl( 20,90%, 70%) 83.3%\n\t);\n}\n.edit > #bar > #previews > :not(h2) {\n\theight: auto;\n\tmax-width: 50%;\n\tobject-fit: contain;\n}\n#previews > h2 {\n\tflex-grow: 1;\n\tfont-size: .9rem;\n\tline-height: 1.4;\n\tdisplay: flex;\n\ttext-align: center;\n\talign-items: center;\n\tjustify-content: center;\n}\n#previews:hover > h2 {\n\ttransform: translateY(-2px);\n}\n\n/* -- */\n\n#fields {\n\tdisplay: flex;\n\tflex-direction: column;\n\toverflow: hidden scroll;\n\tpadding: 1rem;\n\tflex: 0 1 auto;\n\tbackground: var(--bg);\n}\n#presets,\n#fields > label {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n}\n#fields > label+label {\n\tmargin-top: 0.5rem;\n}\n#fields > label:focus-within{\n\tfont-weight: bold;\n}\n#fields > label > * {\n\twidth: calc(100% - 4.5rem);\n\theight: 1rem;\n\tborder-radius: 0.5rem;\n\tborder: 0.15rem solid var(--bg-x);\n\tfont-size: 0.8rem;\n}\n#presets:focus-within,\n#fields > label > :focus,\n#fields > label > :hover {\n\tborder-color: var(--txt);\n}\n#fields > label > #presets {\n\toverflow: hidden;\n\theight: 1.5rem;\n}\n#presets > * {\n\tflex-grow: 1;\n\theight: 100%;\n\tfont-weight: normal;\n}\n#presets > :hover {\n\tbackground: var(--bg);\n}\n#presets > :focus {\n\tbackground: var(--txt);\n\tcolor: var(--bg);\n}\n#fields > label > #text {\n\ttext-align: center;\n\tfont-weight: bold;\n\tresize: none;\n\tline-height: 1.1;\n\toverflow: hidden scroll;\n\tbackground: var(--bg);\n\theight: auto;\n}\n#text::placeholder {\n\tcolor: inherit;\n}\n#text::selection {\n\tcolor: var(--bg);\n\tbackground: var(--txt);\n}\ninput[type=checkbox] {\n\tcursor: pointer;\n}\ninput[type=range] {\n\t-webkit-appearance: none;\n\tcursor: ew-resize;\n\t--gradient: transparent, transparent;\n\t--rainbow: hsl(0, 80%, 75%), hsl(30, 80%, 75%), hsl(60, 80%, 75%), hsl(90, 80%, 75%), hsl(120, 80%, 75%), hsl(150, 80%, 75%), hsl(180, 80%, 75%), hsl(210, 80%, 75%), hsl(240, 80%, 75%), hsl(270, 80%, 75%), hsl(300, 80%, 75%), hsl(330, 80%, 75%);\n\tbackground: linear-gradient(90deg, var(--gradient)), linear-gradient(90deg, var(--rainbow));\n}\ninput[type=range]::-webkit-slider-thumb {\n\t-webkit-appearance: none;\n\ttransition: inherit;\n\tbackground: var(--bg);\n\twidth: 1rem;\n\theight: 1rem;\n\tborder: 0.1rem solid var(--txt);\n\ttransform: scale(1.5);\n\tborder-radius: 100%;\n}\ninput[type=range]:hover::-webkit-slider-thumb {\n\tbackground: var(--bg-x);\n}\ninput[type=range]:focus::-webkit-slider-thumb {\n\tborder-color: var(--bg);\n\tbackground: var(--txt);\n}\ninput[type=range]::-moz-range-thumb {\n\ttransition: inherit;\n\tbackground: var(--bg);\n\twidth: 1rem;\n\theight: 1rem;\n\tborder: 0.1rem solid var(--txt);\n\ttransform: scale(1.5);\n\tborder-radius: 100%;\n\tbox-sizing: border-box;\n}\ninput[type=range]:hover::-moz-range-thumb {\n\tbackground: var(--bg-x);\n}\ninput[type=range]:focus::-moz-range-thumb {\n\tborder-color: var(--bg);\n\tbackground: var(--txt);\n}\ninput#light,\ninput#fade,\ninput#vignette {\n\t--gradient: black, #8880, white\n}\ninput#contrast {\n\t--gradient: gray, #8880\n}\ninput#warmth,\ninput#tilt {\n\t--gradient: #88f, #8880, #ff8\n}\ninput#tint,\ninput#pan {\n\t--gradient: #f8f, #8880, #8f8\n}\ninput#sepia {\n\t--gradient: #8880, #aa8\n}\ninput#hue,\ninput#rotate {\n\t--gradient: var(--rainbow), var(--rainbow)\n}\ninput#saturate {\n\t--gradient: gray, #8880 50%, blue, magenta\n}\ninput#blur {\n\t--gradient: #8880, gray\n}\ninput#scale,\ninput#pillarbox,\ninput#letterbox {\n\t--gradient: black, white\n}\n`;const o={light:{en:"light",es:"brillo",fr:"lumin",it:"lumin",pt:"brilho",zh:"亮度"},contrast:{en:"contrast",es:"contraste",fr:"contraste",it:"contrasto",pt:"contraste",zh:"对比度"},warmth:{en:"warmth",es:"calor",fr:"chaleur",it:"calore",pt:"calor",zh:"温度"},tint:{en:"tint",es:"tinción",fr:"teinte",it:"tinta",pt:"verde",zh:"色调"},sepia:{en:"sepia",es:"sepia",fr:"sépia",it:"seppia",pt:"sépia",zh:"泛黄"},hue:{en:"hue",es:"tono",fr:"ton",it:"tonalità",pt:"matiz",zh:"色相"},saturate:{en:"saturate",es:"satura",fr:"sature",it:"saturare",pt:"satura",zh:"饱和度"},blur:{en:"blur",es:"difuminar",fr:"flou",it:"sfocatura",pt:"enevoa",zh:"模糊"},fade:{en:"fade",es:"fundido",fr:"fondu",it:"svanisci",pt:"fundido",zh:"淡出"},vignette:{en:"vignette",es:"viñeta",fr:"vignette",it:"vignetta",pt:"vinheta",zh:"虚光照"},rotate:{en:"rotate",es:"rota",fr:"pivote",it:"ruoti",pt:"rota",zh:"旋转"},scale:{en:"scale",es:"zoom",fr:"zoom",it:"scala",pt:"zoom",zh:"大小"},pan:{en:"pan",es:"panea",fr:"pan",it:"sposti-h",pt:"panea",zh:"左右移动"},tilt:{en:"tilt",es:"inclina",fr:"incline",it:"sposti-v",pt:"empina",zh:"上下移动"},pillarbox:{en:"pillarbox",es:"recorta-h",fr:"taille-h",it:"tagli-h",pt:"recorta-h",zh:"左右裁剪"},letterbox:{en:"letterbox",es:"recorta-v",fr:"taille-v",it:"tagli-v",pt:"recorta-v",zh:"上下裁剪"},text:{en:"text",es:"texto",fr:"texte",it:"testo",pt:"texto",zh:"文字"},mirror:{en:"mirror",es:"refleja",fr:"réfléch",it:"rispecchi",pt:"refleja",zh:"反射"},freeze:{en:"freeze",es:"pausa",fr:"arrête",it:"pausa",pt:"pausa",zh:"暂停"},presets:{en:"presets",es:"estilos",fr:"styles",it:"stili",pt:"estilos",zh:"预设"},preset:{en:"preset: ",es:"estilo: ",fr:"style: ",it:"stile: ",pt:"estilo: ",zh:"预设:"},reset:{en:"reset",es:"reini",fr:"réinit",it:"reset",pt:"reini",zh:"重置"},open_tip:{en:"Open",es:"Abre",fr:"Ouvre",it:"Apri",pt:"Aberto",zh:"打开"},close_tip:{en:"Close",es:"Cierra",fr:"Ferme",it:"Chiudi",pt:"Feche",zh:"合起"},minimize_tip:{en:"Minimize",es:"Minimizas",fr:"Minimise",it:"Minimizzi",pt:"Minimiza",zh:"合起"},previews_tip:{en:" previews",es:" visualizaciones",fr:" aperçus",it:" anteprima",pt:"visualizações",zh:"预览"},studio_tip:{en:" studio",es:" estudio",fr:" studio",it:" studio",pt:" estúdio",zh:"画室"},text_tip:{en:"Write text here",es:"Escribe el texto aquí",fr:"Écrivez du texte ici",it:"Scrivi il testo qui",pt:"Escreva o texto aqui",zh:"在这里写字"},donate_tip:{en:"Donate to the dev",es:"Donas al dev",fr:"Fais un don au dev",it:"Donare al dev",pt:"Você doa para o dev",zh:"捐款给作者"}};i.lang=["en","es","fr","it","pt","zh"].find(t=>t===navigator.language.split("-")[0])||"en";for(const t in o)o[t]=o[t][i.lang];const l=document.createElement("section");l.id="fields";const c={light:"range",contrast:"range",warmth:"range",tint:"range",sepia:"range_positive",hue:"range_loop",saturate:"range",blur:"range_positive",fade:"range",vignette:"range",rotate:"range_loop",scale:"range_positive",pan:"range",tilt:"range",pillarbox:"range_positive",letterbox:"range_positive",text:"textarea",mirror:"checkbox",freeze:"checkbox",presets:"radio"},d={light:0,contrast:0,warmth:0,tint:0,sepia:0,hue:0,saturate:0,blur:0,fade:0,vignette:0,rotate:0,scale:0,pan:0,tilt:0,pillarbox:0,letterbox:0,text:"",mirror:!1,freeze:!1,presets:"reset"},p=Object.fromEntries(Object.entries(JSON.parse(window.localStorage.getItem("mercator-studio-values-20"))||{}).filter(([t])=>t in d)),u={reset:{},concorde:{contrast:.1,warmth:-.25,tint:-.05,saturate:.2},mono:{light:.1,contrast:-.1,sepia:.8,saturate:-1,vignette:-.5},matcha:{light:.1,tint:-.75,sepia:1,hue:.2,vignette:.3,fade:.3},deepfry:{contrast:1,saturate:.5}},m={...d,...p,freeze:!1},h=Object.fromEntries(Object.entries(m).map(([t,e])=>{let i;const r=c[t];switch(r){case"textarea":(i=document.createElement("textarea")).rows=3,i.placeholder=`\n🌈 ${o.text_tip} 🌦️`,i.addEventListener("input",()=>f(i,i.value.replace(/--/g,"―").replace(/\\sqrt/g,"√").replace(/\\pm/g,"±").replace(/\\times/g,"×").replace(/\\cdot/g,"·").replace(/\\over/g,"∕").replace(/(\^|\_)(\d+)/g,(t,e,n)=>n.split("").map(t=>"₀₁₂₃₄₅₆₇₈₉⁰¹²³⁴⁵⁶⁷⁸⁹"[10*("^"===e)+parseInt(t)]).join(""))));break;case"checkbox":(i=document.createElement("input")).type="checkbox",i.addEventListener("change",()=>f(i,i.checked));break;case"radio":(i=document.createElement("label")).append(...Object.keys(u).map(t=>{const e=document.createElement("button"),n="reset"===t;return e.textContent=n?o.reset:t,e.setAttribute("aria-label",o.preset+e.textContent),e.addEventListener("click",e=>{e.preventDefault(),Object.entries({...d,...u[t]}).filter(([t])=>!["radio","checkbox"].includes(c[t])).forEach(([t,e])=>f(h[t],e))}),e}));break;default:(i=document.createElement("input")).type="range",i.min=("range_positive"===r)-1,i.max=1;const t=i.max-i.min;i.step=t/32,i.addEventListener("keydown",({code:e,ctrlKey:n,shiftKey:r})=>{"Digit0"===e&&g(i),i.step=t/(r?512:n?128:32)}),i.addEventListener("keyup",()=>i.step=t/32),i.addEventListener("input",()=>{i.focus(),f(i,i.valueAsNumber)}),i.addEventListener("wheel",t=>{t.preventDefault(),i.focus();const e=i.getBoundingClientRect().width,n=-t.deltaX,r=t.deltaY,a=(Math.abs(n)>Math.abs(r)?n:r)/e,s=i.max-i.min,o=i.valueAsNumber+a*s,l=Math.min(Math.max(o,i.min),i.max),c=Math.round(l/i.step)*i.step;f(i,c)}),i.addEventListener("contextmenu",t=>{t.preventDefault(),g(i)})}if(f(i,e),i.id=t,!n||!["warmth","tint"].includes(t)){let e=document.createElement("label");e.textContent=o[t],e.append(i),l.append(e)}return[t,i]}));function f(t,e){m[t.id]=t.value=t.checked=e,window.localStorage.setItem("mercator-studio-values-20",JSON.stringify(m))}function g(t){f(t,d[t.id])}const b="http://www.w3.org/2000/svg",v=document.createElementNS(b,"svg"),x=document.createElementNS(b,"filter");x.id="filter";const w=document.createElementNS(b,"feComponentTransfer"),z=Object.fromEntries(["R","G","B"].map(t=>{const e=document.createElementNS(b,"feFunc"+t);return e.setAttribute("type","table"),e.setAttribute("tableValues","0 1"),[t,e]}));w.append(...Object.values(z)),x.append(w),v.append(x);const y=document.createElement("label");y.htmlFor="minimize",y.dataset.off=`${o.minimize_tip}${o.previews_tip} (ctrl + shift + m)`,y.dataset.on=`${o.open_tip}${o.previews_tip} (ctrl + shift + m)`,y.textContent=y.dataset.off;const E=document.createElement("label");E.htmlFor="previews",E.dataset.off=`${o.open_tip}${o.studio_tip} (ctrl + m)`,E.dataset.on=`${o.close_tip}${o.studio_tip} (ctrl + m)`,E.textContent=E.dataset.off;const k=document.createElement("label");k.htmlFor="donate",k.textContent=o.donate_tip;const L=document.createElement("section");L.id="tips",L.append(y,E,k);const _=()=>{L.querySelectorAll(".show").forEach(t=>t.classList.remove("show"));const t=L.querySelector(".hover")||L.querySelector(".focus");t&&t.classList.add("show")},M=(t,e)=>{t.addEventListener("mouseenter",()=>{e.classList.add("hover"),_()}),t.addEventListener("mouseleave",()=>{e.classList.remove("hover"),_()}),t.addEventListener("focus",()=>{e.classList.add("focus"),_()}),t.addEventListener("blur",()=>{e.classList.remove("focus"),_()})},$=document.createElement("section");$.id="bar";const S=document.createElement("button");S.id="minimize",S.textContent="◀";const A=()=>{i.classList.remove("edit"),i.classList.toggle("minimize"),S.focus();const t=i.classList.contains("minimize");S.textContent=t?"▶":"◀",y.textContent=y.dataset[t?"on":"off"],y.classList.remove("focus"),_()};S.addEventListener("click",A),M(S,y);const j=document.createElement("a");j.id="donate",j.href="https://ko-fi.com/xingyzt",j.target="_blank",j.textContent="🤍",j.setAttribute("aria-label",o.donate_tip),M(j,k);const C=document.createElement("button");C.id="previews";const O=()=>{i.classList.remove("minimize"),i.classList.toggle("edit"),C.focus();const t=i.classList.contains("edit");t?Object.values(h)[0].focus():C.focus(),E.textContent=E.dataset[t?"on":"off"],E.classList.remove("focus"),_()};C.addEventListener("click",O),M(C,E),window.addEventListener("keydown",t=>{"KeyM"==t.code&&t.ctrlKey&&(t.preventDefault(),t.shiftKey?A():O())});const D=document.createElement("video");D.setAttribute("playsinline",""),D.setAttribute("autoplay",""),D.setAttribute("muted","");const R=Object.fromEntries(["buffer","freeze","display"].map(t=>{const e=document.createElement("canvas"),n=e.getContext("2d");return[t,{element:e,context:n}]})),B=document.createElement("h2");B.id="title",B.innerText="Mercator\nStudio",C.append(D,B,R.buffer.element),$.append(S,C,j),i.append($,L,l),e.append(i,r,v),document.body.append(t);const I=(t,e)=>(t+1)**e,T=(t,e=32)=>Array(e).fill(0).map((n,i)=>Math.pow(i/(e-1),2**t)).join(" "),q=t=>100*t+"%",F=8;let N=0;const U={state:!1,init:!1,image:document.createElement("img"),canvas:R.freeze};function V(t,e){const i=[t/2,e/2],r=[0,0,t,e],{context:a}=R.buffer;a.clearRect(...r),h.hue.value%=1,h.rotate.value%=1;let o=m,l=q(I(o.light,2)),c=q(I(o.contrast,3)),d=n?0:o.warmth,p=n?0:o.tint,u=q(o.sepia),f=360*o.hue+"deg",g=q(F**o.saturate),b=o.blur*t/16+"px",v=o.fade,x=o.vignette,w=2*o.rotate*Math.PI,y=I(o.scale,2),E=o.mirror,k=o.pan*t,L=o.tilt*e,_=o.pillarbox*t/2,M=o.letterbox*e/2,$=o.text.split("\n");if(z.R.setAttribute("tableValues",T(p/2-d)),z.G.setAttribute("tableValues",T(-p)),z.B.setAttribute("tableValues",T(d+p/2)),a.filter=`\n\t\t\tbrightness(${l})\n\t\t\tcontrast(${c})\n\t\t\t${"url(#filter)".repeat(Boolean(d||p))}\n\t\t\tsepia(${u})\n\t\t\thue-rotate(${f})\n\t\t\tsaturate(${g})\n\t\t\tblur(${b})\n\t\t`,a.translate(...i),w&&a.rotate(w),y-1&&a.scale(y,y),E&&a.scale(-1,1),(k||L)&&a.translate(k,-L),a.translate(...i.map(t=>-t)),U.init){U.canvas.context.drawImage(D,...r);let t=U.canvas.element.toDataURL("image/png");U.image.setAttribute("src",t),U.init=!1}else U.state?a.drawImage(U.image,...r):D.srcObject?a.drawImage(D,...r):"18, 100%, 68%; -10,100%,80%; 5, 90%, 72%; 48, 100%, 75%; 36, 100%, 70%; 20, 90%, 70%".split(";").forEach((n,i)=>{a.fillStyle=`hsl(${n})`,a.fillRect(i*t/6,0,t/6,e)});if(a.setTransform(1,0,0,1,0,0),a.filter="brightness(1)",v){let t=100*Math.sign(v),e=Math.abs(v);a.fillStyle=`hsla(0,0%,${t}%,${e})`,a.fillRect(...r)}if(x){let t=100*Math.sign(x),e=Math.abs(x),n=a.createRadialGradient(...i,0,...i,i.reduce((t,e)=>Math.sqrt(t**2+e**2)));n.addColorStop(0,`hsla(0,0%,${t}%,0`),n.addColorStop(1,`hsla(0,0%,${t}%,${e}`),a.fillStyle=n,a.fillRect(...r)}if(_&&(a.clearRect(0,0,_,e),a.clearRect(t,0,-_,e)),M&&(a.clearRect(0,0,t,M),a.clearRect(0,e,t,-M)),$){const n=.9*(t-2*_),r=.9*(e-2*M),o=$.length;a.font=`bold ${n}px ${s}`,a.textAlign="center",a.textBaseline="middle";let l=a.measureText("0"),c=l.actualBoundingBoxAscent+l.actualBoundingBoxDescent,d=$.reduce((t,e)=>Math.max(t,a.measureText(e).width),0);const p=Math.min(n**2/d,r**2/c/o);a.font=`bold ${p}px ${s}`,l=a.measureText("0"),c=1.5*(l.actualBoundingBoxAscent+l.actualBoundingBoxDescent),a.lineWidth=p/8,a.strokeStyle="black",a.fillStyle="white",$.forEach((t,e)=>{let n=[...i];n[1]+=c*(e-o/2+.5),a.strokeText(t,...n),a.fillText(t,...n)})}R.display.context.clearRect(...r),R.display.context.drawImage(R.buffer.element,0,0)}h.freeze.addEventListener("change",()=>{U.state=U.init=h.freeze.checked});class K extends MediaStream{constructor(t){super(t),D.srcObject=t;const{width:e,height:n}=t.getVideoTracks()[0].getSettings();Object.values(R).forEach(t=>{t.element.width=e,t.element.height=n}),clearInterval(N);N=setInterval(V,1e3/30,e,n);const i=R.display.element.captureStream(30);return i.addEventListener("inactive",()=>{t.getTracks().forEach(t=>t.stop()),R.display.context.clearRect(...fill),D.srcObject=null}),i}}MediaDevices.prototype.old_getUserMedia=MediaDevices.prototype.getUserMedia,MediaDevices.prototype.getUserMedia=(async t=>t&&t.video&&!t.audio?new K(await navigator.mediaDevices.old_getUserMedia(t)):navigator.mediaDevices.old_getUserMedia(t))})()' aria-label='Bookmarklet'>
<svg height='32' viewBox="2 2 20 20"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" fill="#444"/></svg>
<span hidden>Mercator Studio</span>
</a>
</section>
<button id='play-video'>Test it out! <noscript>(requires JavaScript)</noscript></button>
<video width='800' height='450'></video>
<section id='readme'>
Mercator Studio gives you fine control over your appearance on Google Meet.
Precisely adjust lighting and colors:
· Exposure & Contrast
· Temperature & Tint
· Hue & Saturation
· Sepia & Blur
· Fade & Vignette
Move the focus to where you want it:
· Rotate, Scale, Mirror & Flip
· Horizontal & Vertical Translate
· Pillarbox & Letterbox Crop
Write text & emoji in front of your face:
· Auto-adjusts size to fit any length of text onto the screen.
· Auto-converts \sqrt to √, \times to ×, \cdot to ·, \pm to ±, ^number to ¹², and _number to ₄₂.
Somewhat nice presets:
· Concorde
· Mono
· Matcha
· Deepfry
Scroll, drag, or use arrow keys on the sliders to adjust; Right click or press 0 on them to reset; And hold down Ctrl or Shift for finer steps.
Ctrl + M to open/close the interface. Ctrl + Shift + M to minimize it.
Translated for português, español, italiano, français, & 中文.
Changelog:
· 2.2 Translate from EN into PT, ES, IT, FR, and ZH.
· 2.1 Improve keyboard navigation.
· 2.0 Redesign for Google Meet’s new look.
· 1.19 Add mirroring; Dark mode support.
· 1.18 Make textbox auto-resize; Ctrl or Shift for finer steps.
· 1.17 Fix flickering and window-focus issues.
· 1.16 Add freeze feature (thanks @napsav).
· 1.15 Add toggle to super tiny mode.
· 1.14 Add math auto-convert.
· 1.13 Preserve values across sessions.
· 1.12 Luminance-preserving temperature & tint.
· 1.11 Multiline text input; Rebranded as Mercator Studio for Google Meet.
· 1.10 Sync camera; Capture scroll; Right-click reset; Firefox support.
· 1.9 Add text & emoji input.
· 1.8 Add presets; Matched UI with material design.
· 1.7 Add color balance tools and refined UI.
· 1.6 Add fog.
· 1.5 Add vignettes.
· 1.4 Converted to Chrome extension.
· 1.3 Fix the blur slider's range.
· 1.2 Add cropping.
· 1.1 Add a way to reset everything.
· 1.0 Hello world!
Source code: https://github.com/FlyOrBoom/mercator.
Available for other browsers: https://x-ing.space/mercator.
Unfortunately, temperature & tint filters don't work in Firefox.
(C) Xing Liu 2020–2021, MIT License.
Check out other things I’ve made at https://x-ing.space.
</section>
</main>
<script src='src/script.js'></script>
<script>
const video = document.querySelector('video')
const play = document.querySelector('#play-video')
play.addEventListener('click',()=>{
navigator.mediaDevices.getUserMedia({
video: true
}).then( stream => {
video.srcObject = stream
video.play()
video.style.display = 'block'
play.remove()
document.querySelector('aside').shadowRoot.querySelector('#previews').focus()
})
})
</script>
</body>
</html>