@inv8der/ishihara
Advanced tools
Comparing version 0.7.0 to 0.8.0
@@ -0,5 +1,5 @@ | ||
declare type ColorCoords = [number, number, number]; | ||
declare type ColorRange = (percentage: number) => string; | ||
declare type DeficiencyType = 'normal' | 'protanopia' | 'protanomaly' | 'deuteranopia' | 'deuteranomaly' | 'tritanopia' | 'tritanomaly' | 'achromatopsia' | 'achromatomaly'; | ||
export declare class DotGenerator extends EventTarget { | ||
@@ -17,3 +17,3 @@ private _worker; | ||
export declare function generateConfusionLines(type: 'deutan' | 'protan' | 'tritan'): ColorRange[]; | ||
export declare function generateConfusionLines(type: 'deutan' | 'protan' | 'tritan', amount?: number): ColorRange[]; | ||
@@ -40,2 +40,3 @@ declare type GenerateParams = ConstructorParameters<typeof DotGenerator>[0] & { | ||
private _transforms; | ||
constructor(width: number, height: number, dots?: Point[]); | ||
get width(): number; | ||
@@ -45,4 +46,4 @@ get height(): number; | ||
set dots(dots: Point[]); | ||
constructor(width: number, height: number, dots?: Point[]); | ||
simulateColorBlindness(type: DeficiencyType): void; | ||
private _isPointInImage; | ||
simulateColorBlindness(type: 'deutan' | 'tritan' | 'protan', severity?: number): void; | ||
setColors(mode: 'deutan' | 'tritan' | 'protan'): void; | ||
@@ -63,4 +64,6 @@ addShape(shape: 'circle' | 'square' | 'triangle'): void; | ||
export declare function simulateColorBlindness(color: string, type: 'deutan' | 'protan' | 'tritan', severity: number): string; | ||
export declare function simulateColorBlindness(rgb: ColorCoords, deficiency: 'deutan' | 'protan' | 'tritan', severity: number): ColorCoords; | ||
export declare function simulateColorBlindness(rgb: string, deficiency: 'deutan' | 'protan' | 'tritan', severity: number): string; | ||
export { } |
export { DotGenerator } from './dot-generator' | ||
export { IshiharaPlate } from './ishihara-plate' | ||
export { generatePlate } from './factory' | ||
export { generateConfusionLines } from './utils' | ||
export { simulateColorBlindness } from './simulations' | ||
export { generateConfusionLines, simulateColorBlindness } from './color-vision' |
import Color from 'colorjs.io' | ||
import { randomInt, generateConfusionLines, isPointInImage } from '../utils' | ||
import math from '../math' | ||
import { generateConfusionLines, simulateColorBlindness } from '../color-vision' | ||
import type { Point } from '../types' | ||
import { brettel } from '../simulations' | ||
import * as shapes from '../shapes' | ||
type Transform = (p: Point) => Point | ||
// type DeficiencyType = 'deutan' | 'tritan' | 'protan' | ||
type DeficiencyType = | ||
| 'normal' | ||
| 'protanopia' | ||
| 'protanomaly' | ||
| 'deuteranopia' | ||
| 'deuteranomaly' | ||
| 'tritanopia' | ||
| 'tritanomaly' | ||
| 'achromatopsia' | ||
| 'achromatomaly' | ||
export default class IshiharaPlate { | ||
@@ -32,49 +22,60 @@ private _width: number | ||
public get width() { | ||
constructor(width: number, height: number, dots: Point[] = []) { | ||
this._width = width | ||
this._height = height | ||
this.dots = dots | ||
} | ||
get width() { | ||
return this._width | ||
} | ||
public get height() { | ||
get height() { | ||
return this._height | ||
} | ||
public get dots() { | ||
get dots() { | ||
return this._dots | ||
} | ||
public set dots(dots: Point[]) { | ||
set dots(dots: Point[]) { | ||
this._dots = dots.map((point) => ({ ...point })) | ||
} | ||
constructor(width: number, height: number, dots: Point[] = []) { | ||
this._width = width | ||
this._height = height | ||
this.dots = dots | ||
} | ||
private _isPointInImage(point: Point): boolean { | ||
const image = this._imageData | ||
public simulateColorBlindness(type: DeficiencyType) { | ||
this._transforms.set('filter', (point) => { | ||
const color = new Color(point.color ?? '#000000').to('srgb') | ||
let transform = brettel.normal | ||
if (!image) { | ||
return false | ||
} | ||
switch (type) { | ||
case 'protanopia': | ||
case 'protanomaly': | ||
case 'deuteranopia': | ||
case 'deuteranomaly': | ||
case 'tritanopia': | ||
case 'tritanomaly': | ||
transform = brettel[type] | ||
break | ||
for (let i = 0; i <= point.radius; i++) { | ||
for (let r = 0; r <= point.radius; r++) { | ||
const x = point.x + Math.cos(i * Math.PI * 2) * r | ||
const y = point.y + Math.sin(i * Math.PI * 2) * r | ||
case 'achromatopsia': | ||
case 'achromatomaly': | ||
break | ||
const index = (Math.floor(y) * image.width + Math.floor(x)) * 4 | ||
const red = image.data[index] | ||
const green = image.data[index + 1] | ||
const blue = image.data[index + 2] | ||
const alpha = image.data[index + 3] | ||
if ((red + green + blue) * (alpha / 255) < 127) { | ||
return true | ||
} | ||
} | ||
} | ||
color.coords = transform(color.coords) | ||
return false | ||
} | ||
simulateColorBlindness(type: 'deutan' | 'tritan' | 'protan', severity = 1) { | ||
this._transforms.set('filter', (point) => { | ||
const color = new Color(point.color ?? '#000000').to('srgb') | ||
color.coords = simulateColorBlindness(color.coords, type, severity) | ||
return { | ||
...point, | ||
color: color.toString(), | ||
color: color.toString({ format: 'hex' }), | ||
} | ||
@@ -84,5 +85,6 @@ }) | ||
public setColors(mode: 'deutan' | 'tritan' | 'protan') { | ||
setColors(mode: 'deutan' | 'tritan' | 'protan') { | ||
const confusionLines = generateConfusionLines(mode) | ||
const i = randomInt(0, confusionLines.length - 1) | ||
// Generates a random integer between 0 (inclusive) and confusionLines.length (exclusive) | ||
const i = math.randomInt(0, confusionLines.length) | ||
const randomConfusionLine = confusionLines[i] | ||
@@ -94,4 +96,4 @@ | ||
const [onColor, offColor] = generatedColors.get(point.id) ?? [ | ||
randomConfusionLine(Math.random() * 0.5), | ||
randomConfusionLine(0.5 + Math.random() * 0.5), | ||
randomConfusionLine(0.8 + Math.random() * 0.2), | ||
randomConfusionLine(0 + Math.random() * 0.2), | ||
] | ||
@@ -103,6 +105,3 @@ | ||
...point, | ||
color: | ||
this._imageData && isPointInImage(this._imageData, point) | ||
? onColor | ||
: offColor, | ||
color: this._isPointInImage(point) ? onColor : offColor, | ||
} | ||
@@ -112,3 +111,3 @@ }) | ||
public addShape(shape: 'circle' | 'square' | 'triangle') { | ||
addShape(shape: 'circle' | 'square' | 'triangle') { | ||
const image = shapes[shape] | ||
@@ -141,3 +140,3 @@ const ratio = Math.min(this.width / image.width, this.height / image.height) | ||
public reset() { | ||
reset() { | ||
this._transforms.set('color', null) | ||
@@ -148,3 +147,3 @@ this._transforms.set('filter', null) | ||
public draw(ctx: CanvasRenderingContext2D) { | ||
draw(ctx: CanvasRenderingContext2D) { | ||
ctx.clearRect(0, 0, this.width, this.height) | ||
@@ -151,0 +150,0 @@ |
@@ -5,2 +5,4 @@ export type Vector2D = [number, number] | ||
export type ColorCoords = [number, number, number] | ||
export interface Point { | ||
@@ -7,0 +9,0 @@ id: number |
{ | ||
"name": "@inv8der/ishihara", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"type": "module", | ||
@@ -26,3 +26,4 @@ "files": [ | ||
"colorjs.io": "^0.4.5", | ||
"kd-tree-javascript": "^1.0.3" | ||
"kd-tree-javascript": "^1.0.3", | ||
"mathjs": "^12.0.0" | ||
}, | ||
@@ -29,0 +30,0 @@ "devDependencies": { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
23654205
42
30673
3
+ Addedmathjs@^12.0.0
+ Added@babel/runtime@7.26.7(transitive)
+ Addedcomplex.js@2.4.2(transitive)
+ Addeddecimal.js@10.5.0(transitive)
+ Addedescape-latex@1.2.0(transitive)
+ Addedfraction.js@4.3.4(transitive)
+ Addedjavascript-natural-sort@0.7.1(transitive)
+ Addedmathjs@12.4.3(transitive)
+ Addedregenerator-runtime@0.14.1(transitive)
+ Addedseedrandom@3.0.5(transitive)
+ Addedtiny-emitter@2.1.0(transitive)
+ Addedtyped-function@4.2.1(transitive)