将颜色通道字节打包成带符号的整数并正确显示为十六进制
Pack color channel bytes into a signed integer and display correctly as hex
我试图将颜色通道字节打包成一个带符号的整数,但生成的整数将无法正确显示为十六进制,因为它是带符号的。在 JavaScript 中有没有简单的方法可以做到这一点?不幸的是我不能声明一个无符号整数。
#-FFFF01
or -16776961
应该导致:
#FF0000FF
or 4278190335
[
[ 'rgba(255, 0, 0, 1.0)' ],
[ 'rgb(34, 12, 64)' ],
[ 'rgb(34, 12, 64, 0.6)' ],
[ 'rgba(34, 12, 64, 0.6)' ],
[ 'rgb(34 12 64 / 0.6)' ],
[ 'rgba(34 12 64 / 0.3)' ],
[ 'rgb(34.0 12 64 / 60%)' ],
[ 'rgba(34.6 12 64 / 30%)' ],
[ 34, 12, 64, 0.3 ]
].forEach(analyze);
/*
* @param {int|String} r [0, 255] or rgba?()
* @param {int} g [0, 255]
* @param {int} b [0, 255]
* @param {Number} a [0, 1]
*/
function rgba2int(r, g, b, a) {
if (typeof r === 'string' && arguments.length === 1) {
const [r1, g1, b1, a1] = r
.match(/^rgba?\((\d+\.?\d*)[,\s]*(\d+\.?\d*)[,\s]*(\d+\.?\d*)[,\s\/]*(.+)?\)$/)
.slice(1);
[r, g, b] = [r1, g1, b1].map(v => parseFloat(v));
a = a1
? a1.endsWith('%')
? parseInt(a1.substring(0, a1.length - 1), 10) / 100
: parseFloat(a1)
: null;
}
return a
? ((r & 0xFF) << 24) + ((g & 0xFF) << 16) + ((b & 0xFF) << 8) + (Math.floor(a * 0xFF) & 0xFF)
: ((r & 0xFF) << 16) + ((g & 0xFF) << 8) + (b & 0xFF);
}
function analyze(input) {
const res = rgba2int(...input);
console.log([
input.join(' ').padEnd(24, ' '),
res.toString(10).padStart(10, ' '),
('#' + res.toString(16)).padStart(11, ' ')
].join(''));
}
.example { display: inline-block; width: 32px; height: 32px; }
.example-1 { background: rgba(255, 0, 0, 1.0); }
.example-2 { background: rgb(34, 12, 64); }
.example-3 { background: rgb(34, 12, 64, 0.6); }
.example-4 { background: rgba(34, 12, 64, 0.6); }
.example-5 { background: rgb(34 12 64 / 0.6); }
.example-6 { background: rgba(34 12 64 / 0.3); }
.example-7 { background: rgb(34.0 12 64 / 60%); }
.example-8 { background: rgba(34.6 12 64 / 30%); }
<!-- https://developer.mozilla.org/en-US/docs/Web/CSS/color#Syntax -->
<div class="example example-1"></div>
<div class="example example-2"></div>
<div class="example example-3"></div>
<div class="example example-4"></div>
<div class="example example-5"></div>
<div class="example example-6"></div>
<div class="example example-7"></div>
<div class="example example-8"></div>
return a
? (((r & 0xFF) << 24) + ((g & 0xFF) << 16) + ((b & 0xFF) << 8) + (Math.floor(a * 0xFF) & 0xFF)) >>> 0
: (((r & 0xFF) << 16) + ((g & 0xFF) << 8) + (b & 0xFF)) >>> 0;
我试图将颜色通道字节打包成一个带符号的整数,但生成的整数将无法正确显示为十六进制,因为它是带符号的。在 JavaScript 中有没有简单的方法可以做到这一点?不幸的是我不能声明一个无符号整数。
#-FFFF01
or-16776961
应该导致:
#FF0000FF
or4278190335
[
[ 'rgba(255, 0, 0, 1.0)' ],
[ 'rgb(34, 12, 64)' ],
[ 'rgb(34, 12, 64, 0.6)' ],
[ 'rgba(34, 12, 64, 0.6)' ],
[ 'rgb(34 12 64 / 0.6)' ],
[ 'rgba(34 12 64 / 0.3)' ],
[ 'rgb(34.0 12 64 / 60%)' ],
[ 'rgba(34.6 12 64 / 30%)' ],
[ 34, 12, 64, 0.3 ]
].forEach(analyze);
/*
* @param {int|String} r [0, 255] or rgba?()
* @param {int} g [0, 255]
* @param {int} b [0, 255]
* @param {Number} a [0, 1]
*/
function rgba2int(r, g, b, a) {
if (typeof r === 'string' && arguments.length === 1) {
const [r1, g1, b1, a1] = r
.match(/^rgba?\((\d+\.?\d*)[,\s]*(\d+\.?\d*)[,\s]*(\d+\.?\d*)[,\s\/]*(.+)?\)$/)
.slice(1);
[r, g, b] = [r1, g1, b1].map(v => parseFloat(v));
a = a1
? a1.endsWith('%')
? parseInt(a1.substring(0, a1.length - 1), 10) / 100
: parseFloat(a1)
: null;
}
return a
? ((r & 0xFF) << 24) + ((g & 0xFF) << 16) + ((b & 0xFF) << 8) + (Math.floor(a * 0xFF) & 0xFF)
: ((r & 0xFF) << 16) + ((g & 0xFF) << 8) + (b & 0xFF);
}
function analyze(input) {
const res = rgba2int(...input);
console.log([
input.join(' ').padEnd(24, ' '),
res.toString(10).padStart(10, ' '),
('#' + res.toString(16)).padStart(11, ' ')
].join(''));
}
.example { display: inline-block; width: 32px; height: 32px; }
.example-1 { background: rgba(255, 0, 0, 1.0); }
.example-2 { background: rgb(34, 12, 64); }
.example-3 { background: rgb(34, 12, 64, 0.6); }
.example-4 { background: rgba(34, 12, 64, 0.6); }
.example-5 { background: rgb(34 12 64 / 0.6); }
.example-6 { background: rgba(34 12 64 / 0.3); }
.example-7 { background: rgb(34.0 12 64 / 60%); }
.example-8 { background: rgba(34.6 12 64 / 30%); }
<!-- https://developer.mozilla.org/en-US/docs/Web/CSS/color#Syntax -->
<div class="example example-1"></div>
<div class="example example-2"></div>
<div class="example example-3"></div>
<div class="example example-4"></div>
<div class="example example-5"></div>
<div class="example example-6"></div>
<div class="example example-7"></div>
<div class="example example-8"></div>
return a
? (((r & 0xFF) << 24) + ((g & 0xFF) << 16) + ((b & 0xFF) << 8) + (Math.floor(a * 0xFF) & 0xFF)) >>> 0
: (((r & 0xFF) << 16) + ((g & 0xFF) << 8) + (b & 0xFF)) >>> 0;