Myndex / SAPC-APCA

APCA (Accessible Perceptual Contrast Algorithm) is a new method for predicting contrast for use in emerging web standards (WCAG 3) for determining readability contrast. APCA is derived form the SAPC (S-LUV Advanced Predictive Color) which is an accessibility-oriented color appearance model designed for self-illuminated displays.
https://git.apcacontrast.com/documentation/APCAeasyIntro
Other
435 stars 14 forks source link

Improve code structure #70

Closed lil5 closed 2 years ago

lil5 commented 2 years ago

Using typescript can help understand at a glance what the function will require and output.

The function that calculates the minimum px per weight instantly concatenates with html, please separate. If I understand correctly it would be

minPixel(lc: number, weight: nummer): number
minPixelToHtml(minPx: number): string
lil5 commented 2 years ago

here is an example of minPixel in typescript

const APCA_SORTED_BY_CONTRAST_LC = [
  [100,  [46.5, 28.0, 18.0, 14.0, 14.0, 14.0, 14.0, 16.0, 18.0]],
  [95 , [48.5, 29.0, 20.5, 14.5, 14.0, 14.0, 14.0, 16.0, 18.0]],
  [90 , [50.0, 30.0, 21.0, 15.0, 14.5, 14.0, 14.0, 16.0, 18.0]],
  [85 , [53.5, 32.0, 22.0, 16.0, 15.0, 14.0, 14.0, 16.0, 18.0]],
  [80 , [56.5, 34.0, 23.0, 17.0, 16.0, 14.5, 14.0, 16.0, 18.0]],
  [75 , [60.0, 36.0, 24.0, 18.0, 17.0, 15.0, 14.0, 16.0, 18.0]],
  [70 , [65.0, 39.0, 27.5, 19.5, 18.0, 16.0, 14.5, 16.0, 18.0]],
  [65 , [71.5, 43.0, 30.5, 21.5, 19.5, 17.0, 15.0, 16.0, 18.0]],
  [60 , [80.0, 48.0, 34.0, 24.0, 21.0, 18.0, 16.0, 16.0, 18.0]],
  [55 , [86.5, 52.0, 37.0, 26.0, 20.5, 18.5, 16.5, 16.0, 18.0]],
  [50 , [92.5, 58.0, 41.0, 29.0, 22.0, 20.0, 17.5, 16.5, 18.0]],
  [45 , [120.0, 72.0, 51.0, 36.0, 27.0, 23.5, 20.0, 18.0, 18.0]],
  [40 , [160.0, 96.0, 68.0, 48.0, 34.0, 29.0, 24.0, 19.0, 18.0]],
  [35 , [220.0, 132.0, 93.5, 66.0, 46.5, 40.0, 33.0, 26.5, 20.0]],
  [30 , [320.0, 192.0, 135.0, 96.0, 68.0, 58.0, 48.0, 38.5, 29.0]],
];

function ApcaLcToPixels(lc: number, weight: number): number | undefined {
  let lc_rounded = Math.round(lc);
  let index_weight: number = (() => {
    switch (weight) {
      case 100: return 0
      case 200: return 1
      case 300: return 2
      case 400: return 3
      case 500: return 4
      case 600: return 5
      case 700: return 6
      case 800: return 7
      case 900: return 8
      default: return undefined
    }
  })();

  let prev: number | undefined;
  for (let i in APCA_SORTED_BY_CONTRAST_LC) {
    let sorted_by_contrast = APCA_SORTED_BY_CONTRAST_LC[i];

    if (prev === undefined) {
      if (lc_rounded >= sorted_by_contrast[0]) {
          return sorted_by_contrast[1][index_weight];
      }
    } else if (lc_rounded < prev && lc_rounded >= sorted_by_contrast[0]) {
      return sorted_by_contrast[1][index_weight];
    }
    prev = sorted_by_contrast[0] as number;
  }
}
Myndex commented 2 years ago

Hello Lucian @lil5

Sorry for the delay in reply, I didn't get a notification for some reason.

The "released" function on npm (the W3 version of APCA) does not concatenate with html, it returns an array of font sizes.

   npm i apca-w3

and the GitHub repo for that version is https://github.com/Myndex/apca-w3 though issues and discussion are best over here.

In that version, fontLookupAPCA() returns an array where [0] is the Lc value, then elements [1] to [9] are the font sizes for weights 100-900. So as an example:

    fontLookupAPCA(45.687);

returns:

    [45.687,117,71,50,36,28,23.5,20,18,18]

i.e. the Lc value is 45.687, and a 400 weight font is 36px

And yes, I need to climb the typescript learning curve.

Does this answer your question? Or would you prefer that a function returned only a single font size as in:

    fontLookupAPCA(45.687, 400);

would return 36

Side question: I'm considering adding interpolation for variable weights, so

    fontLookupAPCA(45.687, 350);

would return 43

Thank you for your comments!

Andy

lil5 commented 2 years ago

Or would you prefer that a function returned only a single font size as in: fontLookupAPCA(45.687, 400);

No, that doesn't make sense looking at the code structure. It would make most usage needlessly inefficient.

lil5 commented 2 years ago

In that version, fontLookupAPCA() returns an array where [0] is the Lc value, then elements [1] to [9] are the font sizes for weights 100-900.

I felt the need to separate the two, returning an object of type would be even more clean as using different arias of an array for different things is not very understandable.

e.g.:

{
  lc_value: 45.687,
  min_px_by_weight: [117,71,50,36,28,23.5,20,18,18]
}
lil5 commented 2 years ago

and the GitHub repo for that version is https://github.com/Myndex/apca-w3 though issues and discussion are best over here.

@Myndex I didn't know if I could trust that code as you aren't using that project yourself for the webapp. Using es6 imports to have one point of truth concerning the Lc calculator will remove old code usage.

Myndex commented 2 years ago

I didn't know if I could trust that code as you aren't using that project yourself for the webapp. Using es6 imports to have one point of truth concerning the Lc calculator will remove old code usage.

Hi @lil5 — that is a by-product of active research. As things are now stabilizing, I have planned on using the APCA-W3 version for the main myndex.com/APCA/ website. The reason I hadn't was the need to respond promptly to testing/changing and issues early on mean making changes on the fly.

BUT ALSO: the APCA-W3 is intended to the Node.js ecosystem, and the website has features not in ACPA-W3 (like cleaning up keystroke entry, creating a URL with a given color pair, and the live text displays). So to use the apca-w3.js file means reworking more of that site than I have time, so I will when I can, but I have some other pressing priorities at the moment.

Also, I've had a plan to replace the current lookups with an algorithmic approach—that kind of thing will me on hte site well before it gets published in the npm package.

Thank you !!

lil5 commented 2 years ago

Also, I've had a plan to replace the current lookups with an algorithmic approach—that kind of thing will me on hte site well before it gets published in the npm package.

Looking forward to seeing that!

Myndex commented 2 years ago

Hello Lucian @lil5

Just FYI, the tool site at myndex.com/APCA/ is now using a version of the apca-w3 package, so I'm going to close this PR for now, but please feel free to reopen or create a new one if you have more thoughts.

Thank you for reading

sondr3 commented 2 years ago

Not to revive closed issues, but I wrote my own tool for WCAG/APCA contrast checking mostly as a learning exercise. I had a really hard time understanding the code for the font calculations but managed to figure it out, and implemented the APCA algorithm from the LaTeX document (so it can definitely be cleaner).

I've seen that you've been looking into improving the code structure/readability and adding tests, so you can take a look if you want for examples of APCA/WCAG in TypeScript: https://github.com/sondr3/a11y-color-contrast.

Myndex commented 1 year ago

Not to revive closed issues, but I wrote my own tool for WCAG/APCA contrast checking mostly as a learning exercise. I had a really hard time understanding the code for the font calculations but managed to figure it out, and implemented the APCA algorithm from the LaTeX document (so it can definitely be cleaner).

Hi @sondr3

I just now saw this message, I'm assuming that because this issue was closed that I wasn't actually notified. The code used in this repo for font assessment is not intended for code integration and not easy to parse I agree.

The code that you actually want to be using is at the APCA-W3 repo, or in the npm package.

https://github.com/Myndex/apca-w3/