SVG radical images via API

I have heard that I can use the API to get SVG radical images. How can I use the API using JavaScript (at the time of writing, ideally v2) to get all non-Unicode radical images (with the Radicals Update of December 2018 if that makes a difference.)

Are you familiar using the APIv2? The SVGs are in the /subjects endpoint, under the JSON path data.character_images.

curl --request GET \
  --url 'https://api.wanikani.com/v2/subjects?types=radical' \
  --header 'accept: application/json' \
  --header 'authorization: Bearer YOUR-KEY-HERE' \
  --header 'wanikani-revision: 20170710'

Since there’s less than 1000 radicals, you should only need to make the one request.

Then, to get all the svg images (assuming you’re familiar with JsonPath notation):
$.data[*].data.character_images[?(@.content_type == 'image/svg+xml')].url

1 Like

There are two copies of each SVG: one with CSS styling, and one without.
I personally prefer the ones without, so you can change the color and thickness.

If you want to style it yourself, here are the initial attributes:

svg.radical {
    fill:none;
    stroke:#000;
    stroke-linecap:square;
    stroke-miterlimit:2;
    stroke-width:68px;
}

The JsonPath to only retrieve the ones without styling:
$.data[*].data.character_images[?(@.content_type == 'image/svg+xml' && @.metadata.inline_styles == false)].url

Alternately: $.data[*].data.character_images[?(@.content_type == 'image/svg+xml' && !@.metadata.inline_styles)].url, but that can resolve ambiguously if some svg doesn’t have the inline_styles metadata for whatever reason.

Thanks for the quick responses! Actually, I’m not familiar with the APIv2, although your wkstats.com:10001 with it is great! How can I get this with JavaScript?

What language are you planning on using to do things with the svgs? If it’s something like JavaScript or python I can whip up a simple script to grab the links.

Can you create it in JavaScript? Thank you!

Here you go. I’ve tested this in Chrome 67 (the version I have at work), so it should work in most browsers released in the past year.

function getRadicalSVGS(v2Key){
	var headers = new Headers({
		"Authorization": `Bearer ${v2Key}`,
		"Accept": "application/json",
		"Wanikani-Revision": "20170710"
	});
	
	return fetch("https://api.wanikani.com/v2/subjects?types=radical", {headers: headers})
	.then(response => {
		if(!response.ok) throw new Error(response.status);
		return response.json();
	})
	.then(data => {
		var radicalSVGs = {};
		data.data.forEach(function(radical){
			var primaryMeaning = radical.data.meanings.find(function(meaning){ // Find the Primary meaning
				return meaning.primary;
			}).meaning.toLowerCase(); // Set the primary meaning
			
			var svgUrl = radical.data.character_images.find(function(image){ // Find the first SVG that does not have styling. Omit the '!' to get the ones with styling.
				return image.content_type == "image/svg+xml" && !image.metadata.inline_styles;
			});
			
			if(svgUrl){ // Not all radicals have an SVG
				radicalSVGs[primaryMeaning] = svgUrl.url;
			};
		});
		return radicalSVGs
	});;
}

getRadicalSVGS("YOUR_V2_KEY_HERE").then(radicalSVGs => {
	// Do whatever you want with the mapping here, for example:
	for (var key in radicalSVGs){
		if(radicalSVGs.hasOwnProperty(key))
			console.log(key + ": " + radicalSVGs[key]);
	}
});
1 Like

This gladiator radical isn’t showing up correctly - can someone explain this?
@rfindley, how does it look right on WK Stats v2?

You need to add the CSS styling to it to get it to render properly.

svg.radical {
    fill:none;
    stroke:#000;
    stroke-linecap:square;
    stroke-miterlimit:2;
    stroke-width:68px;
}

will give you this:

You can also just use the pre-styled ones if you like, just remove the ! from the script I posted.

2 Likes

Great! Can I filter out the radicals with a Unicode codepoint (e.g. ground = 一, so don’t include that one)?

You can check to see if the radical’s characters property is null before doing any work on it.
An updated script:

function getRadicalSVGS(v2Key){
	var headers = new Headers({
		"Authorization": `Bearer ${v2Key}`,
		"Accept": "application/json",
		"Wanikani-Revision": "20170710"
	});
	
	return fetch("https://api.wanikani.com/v2/subjects?types=radical", {headers: headers})
	.then(response => {
		if(!response.ok) throw new Error(response.status);
		return response.json();
	})
	.then(data => {
		var radicalSVGs = {};
		data.data.forEach(function(radical){
			if(radical.data.characters !== null) 
				return;
			
			var primaryMeaning = radical.data.meanings.find(function(meaning){ // Find the Primary meaning
				return meaning.primary;
			}).meaning.toLowerCase(); // Set the primary meaning
			
			var svgUrl = radical.data.character_images.find(function(image){ // Find the first SVG that does not have styling. Omit the '!' to get the ones with styling.
				return image.content_type == "image/svg+xml" && !image.metadata.inline_styles;
			});
			
			if(svgUrl){ // Not all radicals have an SVG
				radicalSVGs[primaryMeaning] = svgUrl.url;
			};
		});
		return radicalSVGs
	});;
}

getRadicalSVGS("YOUR_KEY_HERE").then(radicalSVGs => {
	// Do whatever you want with the mapping here, for example:
	for (var key in radicalSVGs){
		if(radicalSVGs.hasOwnProperty(key))
			console.log(key + ": " + radicalSVGs[key]);
	}
});

There are much fewer of them.

1 Like