mirror of
https://github.com/tuna/mirror-web.git
synced 2025-12-25 20:32:46 +00:00
initial completed version
This commit is contained in:
parent
92ce69c076
commit
5e7f81f61f
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -35,7 +35,9 @@
|
|||
<div class="row">
|
||||
<h3 id="mirror-title">{% fa_svg fas.fa-cube %} 镜像列表 </h3>
|
||||
{% unless page.legacy %}
|
||||
<input type="search" v-model.trim="filter" id="search" ref="search" placeholder="按 / 搜索" autocomplete="off">
|
||||
<span class="input-wrapper input-wrapper-search">
|
||||
<input type="search" v-model.trim="filter" id="search" ref="search" placeholder="按 / 搜索" autocomplete="off">
|
||||
</span>
|
||||
{% endunless %}
|
||||
</div>
|
||||
<table class="table" v-if="mirrorList.length">
|
||||
|
|
@ -69,7 +71,7 @@
|
|||
{% endraw %}
|
||||
{% else %}
|
||||
{% raw %}
|
||||
<tr v-for="mir in filteredMirrorList" :class="['row', 'status-'+mir.status]" :key="mir.name">
|
||||
<tr v-for="mir in mappedMirrorList" :class="['row', 'status-'+mir.status]" :key="mir.name" :display="mir.shown">
|
||||
<td class="col-md-8">
|
||||
<a class="mirror-item-label" data-toggle="popover" data-trigger="hover" data-placement="right"
|
||||
:data-content="mir.description" :href="getURL(mir)" :aria-label="mir.name + ', ' + mir.description">
|
||||
|
|
@ -128,9 +130,11 @@
|
|||
<div id="download-link">
|
||||
<h4>{% fa_svg far.fa-file-zipper %} 下载链接 </h4>
|
||||
<p>常用发行版 iso 和应用工具安装包直接下载</p>
|
||||
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#isoModal">
|
||||
获取下载链接
|
||||
</button>
|
||||
<span class="input-wrapper" style="border-radius: 4px">
|
||||
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#isoModal">
|
||||
获取下载链接
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
{% endunless %}
|
||||
<div class="thuhidden {%if site.issue%}col-md-3{%endif%}">
|
||||
|
|
|
|||
|
|
@ -7,26 +7,26 @@ BOOTSTRAP MODIFICATIONS & TWEAKS
|
|||
}
|
||||
|
||||
.nav > li > a:hover, .nav > li > a:focus{
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: #111;
|
||||
}
|
||||
}
|
||||
|
||||
pre{
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: #ccc;
|
||||
background-color: #272822;
|
||||
}
|
||||
}
|
||||
|
||||
code{
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: #060d0b;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-default {
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: $color_bg_dark;
|
||||
}
|
||||
@include noissue {
|
||||
|
|
@ -37,13 +37,13 @@ code{
|
|||
.navbar-nav > li.active > a {
|
||||
color: $color_thu_purple;
|
||||
border-bottom: 2px solid $color_thu_purple;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_thu_purple_dark;
|
||||
border-bottom-color: $color_thu_purple_dark;
|
||||
}
|
||||
}
|
||||
.navbar-nav > li > a {
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_secondary_dark;
|
||||
}
|
||||
color: $color_secondary;
|
||||
|
|
@ -54,7 +54,7 @@ code{
|
|||
&:hover, &:focus {
|
||||
color: $color_primary !important;
|
||||
background: transparent !important;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_primary_dark !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ code{
|
|||
|
||||
.navbar-header .navbar-brand {
|
||||
color: $color_secondary;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_secondary_dark;
|
||||
&:hover {
|
||||
color: #fff;
|
||||
|
|
@ -82,7 +82,7 @@ code{
|
|||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background: $color_secondary_dark;
|
||||
}
|
||||
background: $color_secondary ;
|
||||
|
|
@ -92,7 +92,7 @@ code{
|
|||
@include noissue {
|
||||
color: white;
|
||||
}
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_bg_dark;
|
||||
}
|
||||
font-weight: 700;
|
||||
|
|
@ -127,7 +127,7 @@ table .row{
|
|||
}
|
||||
}
|
||||
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
.popover{
|
||||
background-color: #282828;
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
|
|
|
|||
|
|
@ -52,11 +52,20 @@
|
|||
animation-duration: 0.2s;
|
||||
animation-timing-function: ease-in;
|
||||
animation-name: icon-exit;
|
||||
|
||||
&::after {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
bottom: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@each $mode in "light", "dark", "darker", "lighter" {
|
||||
&[data-mode="#{$mode}"] {
|
||||
#{$this}-icon[data-active="#{$mode}"] {
|
||||
position: relative;
|
||||
transition: transform .2s ease-out, opacity .2s ease-out;
|
||||
transition-delay: .15s;
|
||||
opacity: .8;
|
||||
|
|
@ -81,6 +90,30 @@
|
|||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@keyframes hint-reveal {
|
||||
0% {
|
||||
transform: translate(0, 50%);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(10px, 50%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "#{$mode}";
|
||||
animation-fill-mode: both;
|
||||
animation-iteration-count: 1;
|
||||
animation-name: hint-reveal;
|
||||
animation-duration: .2s;
|
||||
animation-delay: 2s;
|
||||
@if $mode == "darker" {
|
||||
animation-delay: 20s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -109,9 +142,34 @@
|
|||
z-index: 100000;
|
||||
pointer-events: none;
|
||||
mix-blend-mode: multiply;
|
||||
|
||||
body.darker-cleanup & {
|
||||
transition: opacity 1s ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.label-status {
|
||||
.darker-engage {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 1s ease-in;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
z-index: 100001;
|
||||
background: black;
|
||||
|
||||
body.darker-engaging & {
|
||||
transition: none;
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
.label-status, .label-new {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +184,94 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
&-search {
|
||||
margin: 20px 10px 0 0;
|
||||
float: right;
|
||||
border-radius: 1px;
|
||||
|
||||
input#search {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mirror-list tbody .row:not([display="true"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.brand-img-text {
|
||||
fill: #2f4b68;
|
||||
|
||||
@include dark(&) {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flame-jump {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(1.5);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(-50%, -50%) scale(1.7);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.flames {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -50%);
|
||||
animation: flame-jump .2s infinite linear;
|
||||
use {
|
||||
fill: rgb(240, 100, 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark-switch-hint {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
top: 100%;
|
||||
transform: translate(50%, 0px);
|
||||
border-radius: 8px;
|
||||
box-shadow: rgba(0,0,0,.3) 0 4px 12px;
|
||||
|
||||
text-align: center;
|
||||
padding: 10px 20px;
|
||||
font-size: 12px;
|
||||
z-index: 10;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
transition: opacity .2s ease, transform .2s ease;
|
||||
|
||||
@include dark(&) {
|
||||
background: $color_bg_dark;
|
||||
}
|
||||
|
||||
&-ack {
|
||||
transform: translate(50%, 20px);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('../fonts/sss-regular.otf') format('otf'),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ body {
|
|||
margin: 0;
|
||||
/* height: 100%; */
|
||||
color: $color_secondary;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_secondary_dark;
|
||||
}
|
||||
font-family: $font_default;
|
||||
|
|
@ -33,7 +33,7 @@ p {
|
|||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
color: $color_secondary ;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_secondary_dark;
|
||||
}
|
||||
margin-top: 10px;
|
||||
|
|
@ -46,7 +46,7 @@ img {
|
|||
|
||||
a {
|
||||
color:$color_link;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_link_dark;
|
||||
}
|
||||
padding: 0;
|
||||
|
|
@ -68,7 +68,7 @@ a:hover, a:focus {
|
|||
color: #fff;
|
||||
text-shadow:none;
|
||||
background:$color_secondary;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background: $color_secondary_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ a:hover, a:focus {
|
|||
color: #fff;
|
||||
text-shadow:none;
|
||||
background:$color_secondary;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background: white;
|
||||
color: $color_secondary;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@
|
|||
.hljs-tag { color: #000080 } // Name.Tag
|
||||
.hljs-variable { color: #008080 } // Name.Variable
|
||||
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
.highlight {
|
||||
.hll { background-color: #272822; }
|
||||
.c { color: #75715e } /* Comment */
|
||||
|
|
|
|||
|
|
@ -45,11 +45,19 @@ $color_bg_dark: #222;
|
|||
$color_primary: $color_thu_purple;
|
||||
$color_primary_dark: $color_thu_purple_dark;
|
||||
|
||||
@mixin dark {
|
||||
@mixin dark($cur) {
|
||||
{% unless site.issue %}
|
||||
@each $br in $cur {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@at-root html:not(.forced-light) #{$br} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
@at-root html.forced-dark #{$br} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
@content
|
||||
{% endunless %}
|
||||
|
|
@ -97,7 +105,7 @@ html {
|
|||
body {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background: $color_bg_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -122,18 +130,18 @@ body {
|
|||
|
||||
.status-fail, .status-failed, .status-paused {
|
||||
background-color: #fff4e3;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: #524841;
|
||||
}
|
||||
}
|
||||
.status-syncing {
|
||||
background-color: #e3fffd;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: #254059;
|
||||
}
|
||||
}
|
||||
.sk-wave .sk-rect {
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: $color_secondary_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -142,7 +150,7 @@ body {
|
|||
tbody {
|
||||
tr:hover {
|
||||
background-color: $color_row_hover;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: $color_row_hover_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +172,7 @@ body {
|
|||
}
|
||||
.question-circle {
|
||||
color: #234961;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: #6e9cdb;
|
||||
}
|
||||
}
|
||||
|
|
@ -172,7 +180,7 @@ body {
|
|||
#news {
|
||||
li > a {
|
||||
color: $color_secondary;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_secondary_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -194,7 +202,7 @@ body {
|
|||
#mirror-list {
|
||||
tr:hover {
|
||||
background-color: $color_row_hover;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
background-color: $color_row_hover_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +218,7 @@ body {
|
|||
article {
|
||||
.meta {
|
||||
color: $color_grey;
|
||||
@include dark{
|
||||
@include dark(&) {
|
||||
color: $color_grey_dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -402,7 +410,7 @@ body {
|
|||
url("/static/img/missing@3x.png") 3x,
|
||||
url("/static/img/missing@4x.png") 4x);
|
||||
}
|
||||
@include dark {
|
||||
@include dark(&) {
|
||||
opacity: 1;
|
||||
filter: none;
|
||||
background-image: url(/static/img/missing-dark.png);
|
||||
|
|
|
|||
|
|
@ -36,10 +36,15 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|||
};
|
||||
console.log("喵呜喵呜喵");
|
||||
var modes = ["light", "dark", "darker", "lighter"];
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
modes[0] = 'dark';
|
||||
modes[1] = 'light';
|
||||
var toggle = document.getElementsByClassName('dark-switch')[0];
|
||||
toggle.setAttribute('data-mode', 'dark');
|
||||
}
|
||||
var tmpCtx = document.createElement('canvas').getContext('2d');
|
||||
var vertShaderSrc = "\nattribute vec4 a_pos;\nuniform vec2 u_screen;\nuniform vec2 u_mouse;\nuniform vec2 u_offset;\n\nvarying float v_opacity;\n\nvoid main() {\n vec2 pos_screen = a_pos.xy + u_offset;\n vec2 pos_translated;\n vec2 diff = pos_screen - u_mouse;\n pos_translated.x = pos_screen.x + diff.x * a_pos.z;\n pos_translated.y = pos_screen.y + diff.y * a_pos.z;\n gl_Position.x = pos_translated.x / u_screen.x * 2.0 - 1.0;\n gl_Position.y = - (pos_translated.y / u_screen.y * 2.0 - 1.0);\n gl_Position.z = 0.0;\n gl_Position.w = 1.0;\n\n float dist = sqrt(diff.x * diff.x + diff.y * diff.y);\n // 30 - 50px\n v_opacity = clamp((dist - 30.0) / 20.0, 0.0, 1.0);\n}\n";
|
||||
var fragShaderSrc = "\nprecision mediump float;\nvarying float v_opacity;\n\nvoid main() {\n gl_FragColor = vec4(0.0, 0.0, 0.0, v_opacity);\n}\n";
|
||||
var radialVertShaderSrc = "\n\n";
|
||||
var radialFragShaderSrc = "\n";
|
||||
function loadFont(fn) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var url, req, resp;
|
||||
|
|
@ -157,14 +162,53 @@ function discretize(path) {
|
|||
return loop;
|
||||
}
|
||||
function applyMode(m) {
|
||||
if (m === 'darker') {
|
||||
ensureCanvas();
|
||||
rescanAt(document.body);
|
||||
// TODO: async reassemble
|
||||
reassemble();
|
||||
ensureObs();
|
||||
renderLoop();
|
||||
}
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var tmpl_1, flames_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
document.body.parentElement.classList.remove('forced-light');
|
||||
document.body.parentElement.classList.remove('forced-dark');
|
||||
if (!(m === 'light' || m === 'dark')) return [3 /*break*/, 1];
|
||||
document.body.parentElement.classList.add("forced-".concat(m));
|
||||
return [3 /*break*/, 4];
|
||||
case 1:
|
||||
if (!(m === 'darker')) return [3 /*break*/, 3];
|
||||
document.body.parentElement.classList.add('forced-light');
|
||||
document.body.classList.add('darker-engaging');
|
||||
return [4 /*yield*/, allFonts];
|
||||
case 2:
|
||||
_a.sent();
|
||||
setTimeout(function () {
|
||||
ensureCanvas();
|
||||
rescanAt(document.body);
|
||||
// TODO: async reassemble
|
||||
reassemble();
|
||||
ensureObs();
|
||||
renderLoop();
|
||||
document.body.classList.remove('darker-engaging');
|
||||
}, 100);
|
||||
return [3 /*break*/, 4];
|
||||
case 3:
|
||||
tmpl_1 = document.querySelector('.dark-switch-icon[data-active="lighter"] svg').cloneNode(true);
|
||||
flames_1 = document.querySelector('.flames');
|
||||
renderStopped = true;
|
||||
document.body.classList.add('darker-cleanup');
|
||||
setTimeout(function () {
|
||||
document.body.addEventListener('click', function (e) {
|
||||
e.target.remove();
|
||||
e.preventDefault();
|
||||
var inserted = tmpl_1.cloneNode(true);
|
||||
inserted.style.top = e.pageY + 'px';
|
||||
inserted.style.left = e.pageX + 'px';
|
||||
flames_1.appendChild(inserted);
|
||||
});
|
||||
});
|
||||
_a.label = 4;
|
||||
case 4: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
var mx = 0;
|
||||
var my = 0;
|
||||
|
|
@ -186,20 +230,24 @@ function rescan(mutations, obs) {
|
|||
var n = _b[_a];
|
||||
rescanAt(n);
|
||||
}
|
||||
reassemble();
|
||||
}
|
||||
setTimeout(function () { return reassemble(); });
|
||||
}
|
||||
// TODO: allow scaning arbitrary HTML-side nodes
|
||||
function rescanAt(el) {
|
||||
var _a;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
if ((_a = el.classList) === null || _a === void 0 ? void 0 : _a.contains('sr-only'))
|
||||
return;
|
||||
if ((_b = el.classList) === null || _b === void 0 ? void 0 : _b.contains('dark-switch-hint'))
|
||||
return;
|
||||
// Check if is svg
|
||||
if (el.tagName === 'svg') {
|
||||
rescanSVG(el);
|
||||
return;
|
||||
}
|
||||
if ((_a = el.classList) === null || _a === void 0 ? void 0 : _a.contains('label-status')) {
|
||||
if (((_c = el.classList) === null || _c === void 0 ? void 0 : _c.contains('label-status')) || ((_d = el.classList) === null || _d === void 0 ? void 0 : _d.contains('label-new')) || ((_e = el.classList) === null || _e === void 0 ? void 0 : _e.contains('input-wrapper')) || ((_f = el.classList) === null || _f === void 0 ? void 0 : _f.contains('popover'))) {
|
||||
var r = parseFloat(window.getComputedStyle(el).borderRadius.match(/^[0-9.]+/)[0]);
|
||||
var _b = el.getBoundingClientRect(), width = _b.width, height = _b.height;
|
||||
var _g = el.getBoundingClientRect(), width = _g.width, height = _g.height;
|
||||
var d = "\n M 0 ".concat(r, " A ").concat(r, " ").concat(r, " 0 0 1 ").concat(r, " 0\n L ").concat(width - r, " 0 A ").concat(r, " ").concat(r, " 0 0 1 ").concat(width, " ").concat(r, "\n L ").concat(width, " ").concat(height - r, " A ").concat(r, " ").concat(r, " 0 0 1 ").concat(width - r, " ").concat(height, "\n L ").concat(r, " ").concat(height, " A ").concat(r, " ").concat(r, " 0 0 1 0 ").concat(height - r, "\n z\n ");
|
||||
var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
|
||||
svg.setAttribute('viewbox', "0 0 ".concat(width, " ").concat(height));
|
||||
|
|
@ -213,10 +261,11 @@ function rescanAt(el) {
|
|||
svg.appendChild(path);
|
||||
el.appendChild(svg);
|
||||
svg.classList.add('darker-traced');
|
||||
svg.classList.add('darker-traced-misc');
|
||||
rescanAt(svg);
|
||||
}
|
||||
for (var _i = 0, _c = el.childNodes; _i < _c.length; _i++) {
|
||||
var child = _c[_i];
|
||||
for (var _i = 0, _h = el.childNodes; _i < _h.length; _i++) {
|
||||
var child = _h[_i];
|
||||
if (child.nodeType === Node.TEXT_NODE) {
|
||||
var inner = child.nodeValue;
|
||||
if (!inner)
|
||||
|
|
@ -307,22 +356,28 @@ function splitPathSegs(path) {
|
|||
var seg = segs_1[_i];
|
||||
var _a = seg.match(/^[mM] *(-?[.0-9]+) *(-?[.0-9]+)/), firstMove = _a[0], mx_1 = _a[1], my_1 = _a[2];
|
||||
// console.log(firstMove);
|
||||
var d_1 = firstMove[0] === 'M' ? seg : "M ".concat(last.x + parseFloat(mx_1), " ").concat(last.y + parseFloat(my_1), " ").concat(seg.substring(firstMove.length));
|
||||
var bx = firstMove[0] === 'M' ? parseFloat(mx_1) : last.x + parseFloat(mx_1);
|
||||
var by = firstMove[0] === 'M' ? parseFloat(my_1) : last.y + parseFloat(my_1);
|
||||
var d_1 = "M ".concat(bx, " ").concat(by, " ").concat(seg.substring(firstMove.length).trim());
|
||||
var path_1 = document.createElementNS("http://www.w3.org/2000/svg", 'path');
|
||||
path_1.setAttribute('d', d_1);
|
||||
path_1.classList.add('darker-processed');
|
||||
path_1.classList.add('darker-surrogate');
|
||||
last = path_1.getPointAtLength(path_1.getTotalLength());
|
||||
paths.push([path_1, new Path2D(d_1)]);
|
||||
if (d_1[d_1.length - 1] === 'z' || d_1[d_1.length - 1] === 'Z') {
|
||||
last = { x: bx, y: by };
|
||||
}
|
||||
else {
|
||||
console.error("Cannot find path end: ".concat(d_1));
|
||||
last = { x: bx, y: by };
|
||||
}
|
||||
paths.push([path_1, { x: bx, y: by }, new Path2D(d_1)]);
|
||||
}
|
||||
var tmpCtx = document.createElement('canvas').getContext('2d');
|
||||
var outerPaths = [];
|
||||
for (var _b = 0, paths_1 = paths; _b < paths_1.length; _b++) {
|
||||
var _c = paths_1[_b], path_2 = _c[0], _ = _c[1];
|
||||
var starting = path_2.getPointAtLength(0);
|
||||
var _c = paths_1[_b], path_2 = _c[0], starting = _c[1], _ = _c[2];
|
||||
var outer = true;
|
||||
for (var _d = 0, paths_2 = paths; _d < paths_2.length; _d++) {
|
||||
var _e = paths_2[_d], another = _e[0], repr = _e[1];
|
||||
var _e = paths_2[_d], another = _e[0], _1 = _e[1], repr = _e[2];
|
||||
if (another !== path_2) {
|
||||
if (tmpCtx.isPointInPath(repr, starting.x, starting.y)) {
|
||||
outer = false;
|
||||
|
|
@ -448,11 +503,11 @@ function ensureObs() {
|
|||
}
|
||||
}
|
||||
var textCache = new WeakMap();
|
||||
var assembleCache = new WeakMap();
|
||||
function reassemble() {
|
||||
var traced = document.getElementsByClassName('darker-traced');
|
||||
var assembledBuffer = [];
|
||||
var trig = 0;
|
||||
function assemblePath(paths, sx, sy, scale) {
|
||||
var buf = [];
|
||||
for (var _i = 0, paths_3 = paths; _i < paths_3.length; _i++) {
|
||||
var path = paths_3[_i];
|
||||
var dpath = discretize(path);
|
||||
|
|
@ -464,21 +519,27 @@ function reassemble() {
|
|||
var nx = dpath[(i + 1) % dpath.length].x * scale + sx;
|
||||
var ny = dpath[(i + 1) % dpath.length].y * scale + sy;
|
||||
// Expand a little bit
|
||||
assembledBuffer.push(cx, cy, 0, nx, ny, 0, cx, cy, 100, cx, cy, 100, nx, ny, 100, nx, ny, 0);
|
||||
trig += 2;
|
||||
buf.push(cx, cy, -0.01, nx, ny, -0.01, cx, cy, 100, cx, cy, 100, nx, ny, 100, nx, ny, -0.01);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
var total = [];
|
||||
for (var _i = 0, traced_1 = traced; _i < traced_1.length; _i++) {
|
||||
var trace = traced_1[_i];
|
||||
if (assembleCache.has(trace)) {
|
||||
var cached = assembleCache.get(trace);
|
||||
total.push.apply(total, cached);
|
||||
continue;
|
||||
}
|
||||
var _a = trace.getBoundingClientRect(), x = _a.x, y = _a.y, width = _a.width, height = _a.height;
|
||||
var scale = 1;
|
||||
var populated = [];
|
||||
if (trace.tagName === 'use') {
|
||||
var sym = document.getElementById(trace.getAttribute('xlink:href').substring(1));
|
||||
var vbox = sym.viewBox.baseVal;
|
||||
// TODO: handle browsers without baseVal
|
||||
// TODO: handle origins other than 0,0
|
||||
var scale_1 = width / vbox.width;
|
||||
var scale = width / vbox.width;
|
||||
var vscale = height / vbox.height;
|
||||
// if(scale > vscale * 1.01 || scale < vscale * 0.99)
|
||||
// console.warn(`incompatible scales: ${scale}, ${vscale}`);
|
||||
|
|
@ -487,15 +548,21 @@ function reassemble() {
|
|||
console.warn("Symbol not in cache: ".concat(sym.id));
|
||||
continue;
|
||||
}
|
||||
assemblePath(paths, x, y + window.scrollY, scale_1);
|
||||
populated = assemblePath(paths, x, y + window.scrollY, scale);
|
||||
}
|
||||
else if (trace.tagName === 'svg') {
|
||||
var scale = 1;
|
||||
var vb = trace.getAttribute('viewBox');
|
||||
if (vb) {
|
||||
var _b = vb.split(' ').map(function (e) { return parseFloat(e); }), _ = _b[0], __ = _b[1], vboxw = _b[2], vboxh = _b[3];
|
||||
scale = width / vboxw;
|
||||
}
|
||||
var paths = svgCache[trace.id];
|
||||
if (paths === undefined) {
|
||||
console.warn("SVG not in cache: ".concat(trace.id));
|
||||
continue;
|
||||
}
|
||||
assemblePath(paths, x, y + window.scrollY, scale);
|
||||
populated = assemblePath(paths, x, y + window.scrollY, scale);
|
||||
}
|
||||
else if (trace.classList.contains('darker-text')) {
|
||||
var cached = textCache.get(trace);
|
||||
|
|
@ -505,17 +572,21 @@ function reassemble() {
|
|||
cached = paths.map(function (e) { return e.getAttribute('d'); });
|
||||
textCache.set(trace, cached);
|
||||
}
|
||||
assemblePath(cached, x, y + window.scrollY, scale);
|
||||
populated = assemblePath(cached, x, y + window.scrollY, 1);
|
||||
}
|
||||
assembleCache.set(trace, populated);
|
||||
total.push.apply(total, populated);
|
||||
}
|
||||
// TODO: error on me
|
||||
if (!shaderCtx.gl)
|
||||
return;
|
||||
shaderCtx.gl.bufferData(shaderCtx.gl.ARRAY_BUFFER, new Float32Array(assembledBuffer), shaderCtx.gl.STATIC_DRAW);
|
||||
shaderCtx.triangleCnt = trig * 3;
|
||||
shaderCtx.gl.bufferData(shaderCtx.gl.ARRAY_BUFFER, new Float32Array(total), shaderCtx.gl.STATIC_DRAW);
|
||||
shaderCtx.triangleCnt = total.length / 3;
|
||||
}
|
||||
var renderStopped = false;
|
||||
function renderLoop() {
|
||||
if (renderStopped)
|
||||
return;
|
||||
if (!canvas || !backdrop || !overlay || !shaderCtx.gl)
|
||||
return;
|
||||
canvas.width = window.innerWidth;
|
||||
|
|
@ -525,7 +596,7 @@ function renderLoop() {
|
|||
backdrop.height = window.innerHeight;
|
||||
var ctx = backdrop.getContext('2d');
|
||||
var grad = ctx.createRadialGradient(mx, my, 100, mx, my, 600);
|
||||
grad.addColorStop(0, "#333");
|
||||
grad.addColorStop(0, "#222");
|
||||
grad.addColorStop(1, "#111");
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fillRect(0, 0, backdrop.width, backdrop.height);
|
||||
|
|
@ -557,13 +628,26 @@ function renderLoop() {
|
|||
}
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var dark = document.getElementsByClassName('dark-switch-inner')[0];
|
||||
var hint = document.querySelector('.dark-switch-hint');
|
||||
dark.addEventListener('click', function () {
|
||||
hint === null || hint === void 0 ? void 0 : hint.classList.add('dark-switch-hint-ack');
|
||||
window.localStorage.setItem('2024-april-fools', 'meow');
|
||||
var parent = dark.parentNode;
|
||||
var cur = parent.getAttribute("data-mode");
|
||||
if (cur === 'lighter')
|
||||
return;
|
||||
var idx = (modes.findIndex(function (e) { return e === cur; }) + 1) % modes.length;
|
||||
var next = modes[idx];
|
||||
applyMode(next);
|
||||
parent.setAttribute('data-mode', next);
|
||||
});
|
||||
if (hint) {
|
||||
hint.addEventListener('click', function (e) {
|
||||
hint.classList.add('dark-switch-hint-ack');
|
||||
window.localStorage.setItem('2024-april-fools', 'meow');
|
||||
});
|
||||
if (window.localStorage.getItem('2024-april-fools') === null)
|
||||
hint.classList.remove('dark-switch-hint-ack');
|
||||
}
|
||||
document.addEventListener('mousemove', tracker);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
console.log("喵呜喵呜喵");
|
||||
|
||||
const modes = ["light", "dark", "darker", "lighter"] as const;
|
||||
type Mode = typeof modes[number];
|
||||
const modes = ["light", "dark", "darker", "lighter"];
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
modes[0] = 'dark';
|
||||
modes[1] = 'light';
|
||||
|
||||
const toggle = document.getElementsByClassName('dark-switch')[0];
|
||||
toggle.setAttribute('data-mode', 'dark');
|
||||
}
|
||||
|
||||
type DiscreteLoop = { x: number, y: number }[];
|
||||
const tmpCtx = document.createElement('canvas').getContext('2d')!;
|
||||
|
||||
const vertShaderSrc = `
|
||||
attribute vec4 a_pos;
|
||||
|
|
@ -39,13 +46,6 @@ void main() {
|
|||
}
|
||||
`;
|
||||
|
||||
const radialVertShaderSrc = `
|
||||
|
||||
`
|
||||
|
||||
const radialFragShaderSrc = `
|
||||
`
|
||||
|
||||
async function loadFont(fn: string): Promise<any> {
|
||||
const url = `/static/fonts/${fn}`;
|
||||
const req = await fetch(url);
|
||||
|
|
@ -147,14 +147,41 @@ function discretize(path: string): DiscreteLoop {
|
|||
return loop;
|
||||
}
|
||||
|
||||
function applyMode(m: Mode) {
|
||||
if(m === 'darker') {
|
||||
ensureCanvas();
|
||||
rescanAt(document.body);
|
||||
// TODO: async reassemble
|
||||
reassemble();
|
||||
ensureObs();
|
||||
renderLoop();
|
||||
async function applyMode(m: string) {
|
||||
(document.body.parentElement as HTMLElement).classList.remove('forced-light');
|
||||
(document.body.parentElement as HTMLElement).classList.remove('forced-dark');
|
||||
if(m === 'light' || m === 'dark') {
|
||||
(document.body.parentElement as HTMLElement).classList.add(`forced-${m}`);
|
||||
} else if(m === 'darker') {
|
||||
(document.body.parentElement as HTMLElement).classList.add('forced-light');
|
||||
document.body.classList.add('darker-engaging');
|
||||
await allFonts;
|
||||
setTimeout(() => {
|
||||
ensureCanvas();
|
||||
rescanAt(document.body);
|
||||
// TODO: async reassemble
|
||||
reassemble();
|
||||
ensureObs();
|
||||
renderLoop();
|
||||
document.body.classList.remove('darker-engaging');
|
||||
}, 100);
|
||||
} else {
|
||||
const tmpl = document.querySelector('.dark-switch-icon[data-active="lighter"] svg')!.cloneNode(true);
|
||||
const flames = document.querySelector('.flames')!;
|
||||
|
||||
renderStopped = true;
|
||||
document.body.classList.add('darker-cleanup');
|
||||
setTimeout(() => {
|
||||
document.body.addEventListener('click', e => {
|
||||
(e.target as HTMLElement).remove();
|
||||
e.preventDefault();
|
||||
const inserted = tmpl.cloneNode(true) as HTMLElement;
|
||||
inserted.style.top = e.pageY + 'px';
|
||||
inserted.style.left = e.pageX + 'px';
|
||||
|
||||
flames.appendChild(inserted);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,19 +202,22 @@ function rescan(mutations: MutationRecord[], obs: MutationObserver) {
|
|||
}
|
||||
|
||||
for(const n of m.addedNodes) rescanAt(n as HTMLElement);
|
||||
reassemble();
|
||||
}
|
||||
setTimeout(() => reassemble());
|
||||
}
|
||||
|
||||
// TODO: allow scaning arbitrary HTML-side nodes
|
||||
function rescanAt(el: HTMLElement) {
|
||||
if(el.classList?.contains('sr-only')) return;
|
||||
if(el.classList?.contains('dark-switch-hint')) return;
|
||||
|
||||
// Check if is svg
|
||||
if(el.tagName === 'svg') {
|
||||
rescanSVG(el as unknown as SVGElement);
|
||||
return;
|
||||
}
|
||||
|
||||
if(el.classList?.contains('label-status')) {
|
||||
if(el.classList?.contains('label-status') || el.classList?.contains('label-new') || el.classList?.contains('input-wrapper') || el.classList?.contains('popover')) {
|
||||
const r = parseFloat(window.getComputedStyle(el).borderRadius.match(/^[0-9.]+/)![0]);
|
||||
const { width, height } = el.getBoundingClientRect();
|
||||
const d = `
|
||||
|
|
@ -213,6 +243,7 @@ function rescanAt(el: HTMLElement) {
|
|||
el.appendChild(svg);
|
||||
|
||||
svg.classList.add('darker-traced');
|
||||
svg.classList.add('darker-traced-misc');
|
||||
rescanAt(svg as unknown as HTMLElement);
|
||||
}
|
||||
|
||||
|
|
@ -316,26 +347,31 @@ function splitPathSegs(path: string): SVGPathElement[] {
|
|||
}
|
||||
|
||||
let last = { x: 0, y: 0 };
|
||||
const paths: [SVGPathElement, Path2D][] = [];
|
||||
const paths: [SVGPathElement, { x: number, y: number }, Path2D][] = [];
|
||||
for(const seg of segs) {
|
||||
const [firstMove, mx, my] = seg.match(/^[mM] *(-?[.0-9]+) *(-?[.0-9]+)/)!;
|
||||
// console.log(firstMove);
|
||||
const d = firstMove[0] === 'M' ? seg : `M ${last.x + parseFloat(mx)} ${last.y + parseFloat(my)} ${seg.substring(firstMove.length)}`;
|
||||
const bx = firstMove[0] === 'M' ? parseFloat(mx) : last.x + parseFloat(mx);
|
||||
const by = firstMove[0] === 'M' ? parseFloat(my) : last.y + parseFloat(my);
|
||||
const d = `M ${bx} ${by} ${seg.substring(firstMove.length).trim()}`;
|
||||
|
||||
const path = document.createElementNS("http://www.w3.org/2000/svg", 'path');
|
||||
path.setAttribute('d', d);
|
||||
path.classList.add('darker-processed');
|
||||
path.classList.add('darker-surrogate');
|
||||
last = path.getPointAtLength(path.getTotalLength());
|
||||
paths.push([path, new Path2D(d)]);
|
||||
if(d[d.length-1] === 'z' || d[d.length-1] === 'Z') {
|
||||
last = { x: bx, y: by };
|
||||
} else {
|
||||
console.error(`Cannot find path end: ${d}`);
|
||||
last = { x: bx, y: by };
|
||||
}
|
||||
paths.push([path, { x: bx, y: by }, new Path2D(d)]);
|
||||
}
|
||||
|
||||
const tmpCtx = document.createElement('canvas').getContext('2d')!;
|
||||
const outerPaths: SVGPathElement[] = [];
|
||||
for(const [path, _] of paths) {
|
||||
const starting = path.getPointAtLength(0);
|
||||
for(const [path, starting, _] of paths) {
|
||||
let outer = true;
|
||||
for(const [another, repr] of paths) if(another !== path) {
|
||||
for(const [another, _, repr] of paths) if(another !== path) {
|
||||
if(tmpCtx.isPointInPath(repr, starting.x, starting.y)) {
|
||||
outer = false;
|
||||
break;
|
||||
|
|
@ -466,13 +502,13 @@ function ensureObs() {
|
|||
}
|
||||
|
||||
const textCache: WeakMap<Element, string[]> = new WeakMap();
|
||||
const assembleCache: WeakMap<Element, number[]> = new WeakMap();
|
||||
|
||||
function reassemble() {
|
||||
const traced = document.getElementsByClassName('darker-traced');
|
||||
|
||||
const assembledBuffer: number[] = [];
|
||||
let trig = 0;
|
||||
function assemblePath(paths: string[], sx: number, sy: number, scale: number) {
|
||||
function assemblePath(paths: string[], sx: number, sy: number, scale: number): number[] {
|
||||
const buf: number[] = [];
|
||||
for(const path of paths) {
|
||||
const dpath = discretize(path);
|
||||
if(dpath.length === 1) continue;
|
||||
|
|
@ -485,24 +521,31 @@ function reassemble() {
|
|||
let ny = dpath[(i + 1) % dpath.length].y * scale + sy;
|
||||
|
||||
// Expand a little bit
|
||||
assembledBuffer.push(
|
||||
cx, cy, 0,
|
||||
nx, ny, 0,
|
||||
buf.push(
|
||||
cx, cy, -0.01,
|
||||
nx, ny, -0.01,
|
||||
cx, cy, 100,
|
||||
|
||||
cx, cy, 100,
|
||||
nx, ny, 100,
|
||||
nx, ny, 0,
|
||||
nx, ny, -0.01,
|
||||
);
|
||||
trig += 2;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
const total: number[] = [];
|
||||
for(const trace of traced) {
|
||||
if(assembleCache.has(trace)) {
|
||||
const cached = assembleCache.get(trace)!;
|
||||
total.push(...cached);
|
||||
continue;
|
||||
}
|
||||
|
||||
const { x, y, width, height } = trace.getBoundingClientRect();
|
||||
|
||||
let scale = 1;
|
||||
let populated: number[] = [];
|
||||
|
||||
if(trace.tagName === 'use') {
|
||||
const sym = document.getElementById(trace.getAttribute('xlink:href')!.substring(1)) as unknown as SVGSymbolElement;
|
||||
|
|
@ -520,14 +563,20 @@ function reassemble() {
|
|||
continue;
|
||||
}
|
||||
|
||||
assemblePath(paths, x, y + window.scrollY, scale);
|
||||
populated = assemblePath(paths, x, y + window.scrollY, scale);
|
||||
} else if(trace.tagName === 'svg') {
|
||||
let scale = 1;
|
||||
const vb = trace.getAttribute('viewBox');
|
||||
if(vb) {
|
||||
const [_, __, vboxw, vboxh] = vb.split(' ').map(e => parseFloat(e))!;
|
||||
scale = width / vboxw;
|
||||
}
|
||||
const paths: string[] | undefined = svgCache[trace.id];
|
||||
if(paths === undefined) {
|
||||
console.warn(`SVG not in cache: ${trace.id}`);
|
||||
continue;
|
||||
}
|
||||
assemblePath(paths, x, y + window.scrollY, scale);
|
||||
populated = assemblePath(paths, x, y + window.scrollY, scale);
|
||||
} else if(trace.classList.contains('darker-text')) {
|
||||
let cached = textCache.get(trace);
|
||||
if(!cached) {
|
||||
|
|
@ -536,19 +585,23 @@ function reassemble() {
|
|||
cached = paths.map(e => e.getAttribute('d')!);
|
||||
textCache.set(trace, cached);
|
||||
}
|
||||
assemblePath(cached, x, y + window.scrollY, scale);
|
||||
populated = assemblePath(cached, x, y + window.scrollY, 1);
|
||||
}
|
||||
|
||||
assembleCache.set(trace, populated);
|
||||
total.push(...populated);
|
||||
}
|
||||
|
||||
// TODO: error on me
|
||||
if(!shaderCtx.gl) return;
|
||||
|
||||
shaderCtx.gl.bufferData(shaderCtx.gl.ARRAY_BUFFER, new Float32Array(assembledBuffer), shaderCtx.gl.STATIC_DRAW);
|
||||
shaderCtx.triangleCnt = trig * 3;
|
||||
shaderCtx.gl.bufferData(shaderCtx.gl.ARRAY_BUFFER, new Float32Array(total), shaderCtx.gl.STATIC_DRAW);
|
||||
shaderCtx.triangleCnt = total.length / 3;
|
||||
}
|
||||
|
||||
let renderStopped = false;
|
||||
function renderLoop() {
|
||||
if(renderStopped) return;
|
||||
if(!canvas || !backdrop || !overlay || !shaderCtx.gl) return;
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
|
@ -558,7 +611,7 @@ function renderLoop() {
|
|||
backdrop.height = window.innerHeight;
|
||||
const ctx = backdrop.getContext('2d')!;
|
||||
const grad = ctx.createRadialGradient(mx, my, 100, mx, my, 600);
|
||||
grad.addColorStop(0, "#333");
|
||||
grad.addColorStop(0, "#222");
|
||||
grad.addColorStop(1, "#111");
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fillRect(0, 0, backdrop.width, backdrop.height);
|
||||
|
|
@ -597,14 +650,30 @@ function renderLoop() {
|
|||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const dark = document.getElementsByClassName('dark-switch-inner')[0];
|
||||
const hint = document.querySelector('.dark-switch-hint');
|
||||
|
||||
dark.addEventListener('click', () => {
|
||||
hint?.classList.add('dark-switch-hint-ack');
|
||||
window.localStorage.setItem('2024-april-fools', 'meow');
|
||||
|
||||
const parent = dark.parentNode as HTMLElement;
|
||||
const cur = parent.getAttribute("data-mode");
|
||||
if(cur === 'lighter') return;
|
||||
const idx = (modes.findIndex(e => e === cur) + 1) % modes.length;
|
||||
const next = modes[idx];
|
||||
applyMode(next);
|
||||
parent.setAttribute('data-mode', next);
|
||||
})
|
||||
|
||||
if(hint) {
|
||||
hint.addEventListener('click', e => {
|
||||
hint.classList.add('dark-switch-hint-ack');
|
||||
window.localStorage.setItem('2024-april-fools', 'meow');
|
||||
})
|
||||
|
||||
if(window.localStorage.getItem('2024-april-fools') === null)
|
||||
hint.classList.remove('dark-switch-hint-ack');
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', tracker);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -64,10 +64,13 @@ const vmMirList = new Vue({
|
|||
}
|
||||
return result;
|
||||
},
|
||||
filteredMirrorList: function() {
|
||||
mappedMirrorList: function() {
|
||||
var filter = this.filter.toLowerCase();
|
||||
return this.mirrorList.filter((m) => {
|
||||
return m.is_master && m.name.toLowerCase().indexOf(filter) !== -1;
|
||||
return this.mirrorList.map((m) => {
|
||||
return {
|
||||
...m,
|
||||
shown: m.is_master && m.name.toLowerCase().indexOf(filter) !== -1,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
attribute vec3 a_pos;
|
||||
uniform vec2 u_screen;
|
||||
uniform vec2 u_mouse;
|
||||
uniform vec2 u_offset;
|
||||
|
||||
void main() {
|
||||
vec2 pos_screen = a_pos.xy - u_offset;
|
||||
vec2 pos_translated;
|
||||
pos_translated.x = pos_screen.x + (pos_screen.x - u_mouse.x) * a_pos.z * 1000;
|
||||
pos_translated.y = pos_screen.y + (pos_screen.y - u_mouse.y) * a_pos.z * 1000;
|
||||
gl_Position.x = pos_translated.x / u_screen * 2 - 1;
|
||||
gl_Position.y = pos_translated.y / u_screen * 2 - 1;
|
||||
}
|
||||
Loading…
Reference in New Issue