The simplest option is to load the Hanzi Writer JS directly from the jsdelivr CDN. Just put the following in the head of your webpage:
You can also download a copy of the Hanzi Writer javascript here:
hanzi-writer.min.js - minified for production (30 kb, 9kb gzipped)
hanzi-writer.js - unminified for development (70 kb)
The above scripts will make a global HanziWriter
variable available after the script loads.
If you want to include Hanzi Writer in webpack or node.js, you can install from npm: npm install hanzi-writer
. Then, you can include Hanzi Writer in your code via:
Creating a new HanziWriter
instance requires passing in a target div (either ID or DOM reference),
the character you'd like to render, and configuration options. A simple example is illustrated below.
Assuming in HTML you have:
Then, in Javascript:
You can see the result of this below:
In the above example width and height are the size of the box containing the character in pixels, and padding is the space between the character and the edge of the box, also in pixels. You can configure other options as well, like the color of the character. Below is an example drawn with different sizing and colors:
Hanzi Writer also supports coloring the radical of a character differently. You set the color to display the radical with the radicalColor
option. Below is an example of the word 草 with the radical colored green.
After you create a HanziWriter instance you can animate it by calling the
animateCharacter()
method. In the example below, the character is animated when a button is pressed. the HTML looks like the following:
Then, the corresponding javascript:
There are also a number of options you can configure with animations to control things like the speed of the animation and whether or not the character outline is visible. You can also set a radical color if you'd like to show the character radical while animating. Below is another example of animating with different animation options:
It's common to repeat an animation over and over. You can call
loopCharacterAnimation()
to start and animation that will keep looping. There's a configuration option delayBetweenLoops
you can use to control how much time there is between each animation loop (default 2000 ms). In the example below, the character will wait 3 seconds and then redraw itself forever:
You can pass an onComplete callback when running
animateCharacter({ onComplete: function() { ... }})
that you can use to cause one character to start animating after another finishes. If you prefer to use promises instead, the animateCharacter()
method will also return a promise which resolves when the animation is complete. Below is an example of 2 characters animating in order, one after another with 1 second between drawing each character. The example uses onComplete
to trigger the next character to start after the first finishes. the HTML looks like:
And the javascript:
You can start a quiz by calling the quiz()
method. We can set up a simple quiz with the code below:
Try drawing the character 测 above to get a feel for how quizzes work. If you miss a stroke 3 times it will give you a hint by highlighting the correct stroke. You can configure this behavior by setting the showHintAfterMisses
option to a different number, or you can set showHintAfterMisses: false
to disable it entirely. After a quiz is completed successfully it will flash briefly. You can disable this by setting highlightOnComplete: false
. Below is an example with some of these options changed. The example below also sets showOutline: false
to make it more challenging.
Try drawing the character 鬼 above.
Quizzes on their own are good practice, but they become really poweful when they interact with the rest of your code. The quiz()
method can be passed callbacks that you can use to run code when events happen in the quiz, like getting a stroke right or wrong, or the quiz finishing. The callbacks are called onCorrectStroke
, onMistake
and onComplete
. These callbacks get passed an object containing info about the current state of the quiz. Below is an example of how you can integrate these callbacks:
Try drawing the character 码 above, and watch the output appear in the virtual console.
Aside from the core capability of animating and quizzing, there are several other methods available to control the rendering of a character.
writer.setCharacter(newCharacter)
Load a new character and rerender.
writer.showCharacter()
Show the character if it is currently hidden
writer.hideCharacter()
Hide the character if it is currently shown
writer.showOutline()
Show the character outline if it's currently hidden
writer.hideOutline()
Hide the character outline if it's currently shown
writer.updateColor(colorName, newValue)
Change the value of any color option. For example: writer.updateColor('strokeColor', '#AA12CD')
writer.cancelQuiz()
Immediately cancel the currently running quiz
Hanzi Writer needs to load stroke rendering data in order to draw characters. By default Hanzi Writer will load this data from the jsdelivr CDN using ajax. This is probably fine for embedding Hanzi Writer into a website, but depending on how you're using Hanzi Writer there may be better ways to load character data. For example, if you're buidling a mobile app and want to embed Hanzi Writer into the app it's best to load character data locally so that character data is loaded instantly and without needing an internet connection.
There is a sister repo called hanzi-writer-data which contains the data for each individual character as a separate JSON file. You can host these files from your server and load them via AJAX inside of Hanzi Writer however you see fit. This data can also be loaded via NPM to include individual character data in your JS. Loading character data is way is accomplished via passing a custom closure to the charDataLoader option. An example is shown below using jQuery:
The repo also contains all.json which contain all characters in 1 file, but these files are quite large (28mb) so they're probably not ideal for production use.
If you know in advance which character you'd like to render you can hardcode just the data for that
character into the charDataLoader closure. To do this, you can make use of the hanzi-writer-data NPM module and directly require character data inline. This technique ensures that Hanzi Writer will be able to render the character instantly without needing to wait for an AJAX request to complete. Below is an example of loading character data for the character 人 via the hanzi-writer-data NPM module. First, make sure the hanzi-writer-data module is installed by running:
npm install hanzi-writer-data
.
If you would like to be notified when character data is loaded successfully or when it fails (for example to implement a loading spinner or show an error message), you can pass onLoadCharDataSuccess
and onLoadCharDataError
callbacks when creating a HanziWriter instance. For example:
Sometimes you may want to render Hanzi writer character data but don't need stroke animations or stroke quizzes. Hanzi writer provides 2 static helper methods which make it easy to load and render raw character data.
You can load character data from the Hanzi writer CDN using the static method HanziWriter.loadCharacterData(character, options = {})
. This method will return a promise containing the loaded data for the character, but you can also pass onLoadCharDataSuccess
and onLoadCharDataError
callbacks as options if you prefer. The character data that's loaded will be the same as what's in the hanzi-writer-data repo, which are all parsed out from makemeahanzi.
The trickest part about rendering the SVG paths for Hanzi writer data is that the characters must be transformed to appear on the screen at the desired size, usually in a <g>
tag. For example, to render the SVG for a character at size 128 x 128, the SVG would look something like this:
Fortunately, there's a static method HanziWriter.getScalingTransform(width, height, padding = 0)
which makes this easy. This method returns transform data which you can use in SVG to draw the character at the specified size. Below is an example of loading data for the character 六 and rendering the character SVG at size 150 x 150 inside a div with ID target
:
Using raw character data gives you the full power of SVG to implement visualizations that don't require stroke animation or quizzing. For example, below is an example of using raw character data to implement a stroke fanning visualization of the character 是:
The examples above use raw javascript browser APIs for SVG rendering, but the code would be even simpler using a library to help manage SVG, like svg.js or raphael.js.
If you already have an <SVG>
or <G>
element on the page, you can render a HanziWriter instance into that instead of using a DIV.
This makes it easy to add custom backgrounds like a grid directly in SVG. For example, we can draw a simple grid in SVG like below:
Then, we can render into this SVG by using its ID, just like we can with a normal div:
This is the core class you will interact with.
Set up a new HanziWriter instance the specified DOM element
element
DOM node or ID of the element to render into.
options
object containing additional configuration options. Full options available include:
showOutline:
boolean, default true. Controls whether the outline is shown or hidden on the first render.showCharacter:
boolean, default true. Controls whether the character is shown or hidden on the first render.width:
number. Width of the canvas in px.height:
number. height of the canvas in px.padding:
number, default 20. padding between the character and edge of the canvas in px.strokeAnimationSpeed:
number, default 1. Speed at which to draw each stroke, must be greater than 0. Increase this number to draw strokes faster, decrease to draw strokes slower.strokeHighlightSpeed:
number, default 2. Speed at which to highlight each stroke when givings hints in a quiz, must be greater than 0. Increase this number to highlight faster, decrease to highlight slower.strokeFadeDuration:
number, default 400. Time in milliseconds to transition between showing and hiding strokes when calling writer.show()
and writer.hide()
delayBetweenStrokes:
number, default 1000. Time in milliseconds between each stroke when animating.delayBetweenLoops:
number, default 2000. Time in milliseconds between each animation loop when looping animations.strokeColor:
hex string, default '#555'. The color to draw each stroke.radicalColor:
hex string, default null. The color to draw the radical in the stroke, if radical data is present. Radicals will be drawn the same color as other strokes if this is not set.highlightColor:
hex string, default '#AAF'. The color to use for highlighting in quizzes.outlineColor:
hex string, default '#DDD'. The color of the character outline.drawingColor:
hex string, default '#333'. The color of the lines drawn by users during quizzing.drawingWidth:
number, default 4. The width of the lines drawn by users during quizzing in px.showHintAfterMisses:
integer, default 3. The number of misses before a stroke highlight hint is given to the user. Set to false to disable. This can also be set when creating a quiz.markStrokeCorrectAfterMisses:
integer, default disabled. The number of misses before forcing the stroke to be marked correct. This can also be set when creating a quiz.quizStartStrokeNum:
integer, default 0. This can be set to start the quiz at a stroke other than the first stroke. This can also be set when creating a quiz.acceptBackwardsStrokes:
boolean, default false. Allow stroke to be drawn backwards during quizzing. This can also be set when creating a quiz.highlightOnComplete:
boolean, default true. Controls whether a quiz briefly highlights the character when the user finishes drawing the whole character. This can also be set when creating a quiz.highlightCompleteColor:
hex string, default null. The color to use when highlighting the character on complete in quizzes. If not set, highlightColor
will be used instead. Only relevant if highlightOnComplete
is true
.charDataLoader:
function. Custom function to load charater data. See the section on Loading character data for more info on usage.onLoadCharDataSuccess:
function. Callback for when character data is loaded successfully. This function is called with the data that was loaded. This can be used to implement a loading spinner.onLoadCharDataError:
function. Callback for when character data loading fails. This function is passed whatever the failure reason is from charDataLoader.renderer:
string, default 'svg'. Set this to 'canvas' to render using a 2d canvas instead of SVG. May have better performance on some devices.Show the character if it's currently hidden.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the showing animation is complete.duration:
number, optional. How long the showing animation should take to complete. If not provided then strokeFadeDuration
is used. Passing 0 will make the operation instant.Hide the character if it's currently shown.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the hiding animation is complete.duration:
number, optional. How long the hiding animation should take to complete. If not provided then strokeFadeDuration
is used. Passing 0 will make the operation instant.Show the outline if it's currently hidden.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the showing animation is complete.duration:
number, optional. How long the showing animation should take to complete. If not provided then strokeFadeDuration
is used. Passing 0 will make the operation instant.Hide the outline if it's currently shown.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the hiding animation is complete.duration:
number, optional. How long the hiding animation should take to complete. If not provided then strokeFadeDuration
is used. Passing 0 will make the operation instant.Update the size of the writer instance
options
object containing additional configuration options. Full options include:
width:
number, optional, the new width in pxheight:
number, optional, the new height in pxpadding:
number, optional, the new padding in pxUpdate a color setting.
colorName
string. One of 'strokeColor', 'radicalColor', 'outlineColor', 'highlightColor', or 'drawingColor'.
colorVal
string. A CSS color string like '#AA9913' or 'rgba(255, 255, 10, 0.7)'
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the hiding animation is complete.duration:
number, optional. How long the animation should take to complete. If not provided then strokeFadeDuration
is used. Passing 0 will make the operation instant.Animate the strokes of the character in order
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the animation is complete.Animate a single stroke
strokeNum
number. The stroke number to animate, starting at 0.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the animation is complete.Highlight a single stroke
strokeNum
number. The stroke number to highlight, starting at 0.
options
object containing additional configuration options. Full options include:
onComplete:
function. Called when the animation is complete.Animate the strokes of the character in order, and then restart the animation after it finishes forever.
Pause any currently running animations.
Resume any animations that were previously paused with pauseAnimation()
.
Replace the currently drawn character with a new one. This will reset any quizzes or animations in progress.
character
The character to draw, ex '你'.
Start a quiz.
options
object containing additional configuration options. Full options include:
onComplete:
function(data). Called when the quiz is complete. The function is called with an object containing totalMistakes
which is the total mistakes made during the quiz.onCorrectStroke:
function(data). Called when the user draws a stroke correctly. The function is called with an object containing:
totalMistakes
the total mistakes made during the quiz so far.
strokeNum
the current stroke number.
mistakesOnStroke
the number of mistakes the user made drawing this stroke so far.
strokesRemaining
the number of strokes left until the quiz is complete.
drawnPath
an object containg the pathString
drawn by the user and the points
used for grading.
onMistake:
function(data). Called when the user makes a mistake drawing a stroke. The function is called with an object containing:
totalMistakes
the total mistakes made during the quiz so far.
strokeNum
the current stroke number.
mistakesOnStroke
the number of mistakes the user made drawing this stroke so far.
strokesRemaining
the number of strokes left until the quiz is complete.
drawnPath
an object containg the pathString
drawn by the user and the points
used for grading.
showHintAfterMisses:
integer, default 3. The number of misses before a stroke highlight hint is given to the user. Set to false to disable. This can also be set when creating the writer instance.markStrokeCorrectAfterMisses:
integer, default disabled. The number of misses before forcing the stroke to be marked correct.quizStartStrokeNum:
integer, default 0. This can be set to start the quiz at a stroke other than the first stroke.acceptBackwardsStrokes:
boolean, default false. Allow stroke to be drawn backwards during quizzing.leniency:
float, default 1.0. This can be set to make stroke grading more or less lenient. The closer this is to 0 the more strictly the quiz is graded.highlightOnComplete:
boolean, default true. Controls whether a quiz briefly highlights the character when the user finishes drawing the whole character. This can also be set when creating the writer instance.Cancel the quiz currently in progress
Set up a new HanziWriter instance the specified DOM element
element
DOM node or ID of the element to render into.
character
The character to draw, ex '你'.
options
object containing additional configuration options. Full options available include:
showOutline:
boolean, default true. Controls whether the outline is shown or hidden on the first render.showCharacter:
boolean, default true. Controls whether the character is shown or hidden on the first render.width:
number. Width of the canvas in px.height:
number. height of the canvas in px.padding:
number, default 20. padding between the character and edge of the canvas in px.strokeAnimationSpeed:
number, default 1. Speed at which to draw each stroke, must be greater than 0. Increase this number to draw strokes faster, decrease to draw strokes slower.strokeHighlightSpeed:
number, default 2. Speed at which to highlight each stroke when givings hints in a quiz, must be greater than 0. Increase this number to highlight faster, decrease to highlight slower.strokeFadeDuration:
number, default 400. Time in milliseconds to transition between showing and hiding strokes when calling writer.show()
and writer.hide()
delayBetweenStrokes:
number, default 1000. Time in milliseconds between each stroke when animating.delayBetweenLoops:
number, default 2000. Time in milliseconds between each animation loop when looping animations.strokeColor:
hex string, default '#555'. The color to draw each stroke.radicalColor:
hex string, default null. The color to draw the radical in the stroke, if radical data is present. Radicals will be drawn the same color as other strokes if this is not set.highlightColor:
hex string, default '#AAF'. The color to use for highlighting in quizzes.outlineColor:
hex string, default '#DDD'. The color of the character outline.drawingColor:
hex string, default '#333'. The color of the lines drawn by users during quizzing.drawingWidth:
number, default 4. The width of the lines drawn by users during quizzing in px.showHintAfterMisses:
integer, default 3. The number of misses before a stroke highlight hint is given to the user. Set to false to disable. This can also be set when creating a quiz.markStrokeCorrectAfterMisses:
integer, default disabled. The number of misses before forcing the stroke to be marked correct. This can also be set when creating a quiz.quizStartStrokeNum:
integer, default 0. This can be set to start the quiz at a stroke other than the first stroke. This can also be set when creating a quiz.acceptBackwardsStrokes:
boolean, default false. Allow stroke to be drawn backwards during quizzing. This can also be set when creating a quiz.highlightOnComplete:
boolean, default true. Controls whether a quiz briefly highlights the character when the user finishes drawing the whole character. This can also be set when creating a quiz.highlightCompleteColor:
hex string, default null. The color to use when highlighting the character on complete in quizzes. If not set, highlightColor
will be used instead. Only relevant if highlightOnComplete
is true
.charDataLoader:
function. Custom function to load charater data. See the section on Loading character data for more info on usage.onLoadCharDataSuccess:
function. Callback for when character data is loaded successfully. This function is called with the data that was loaded. This can be used to implement a loading spinner.onLoadCharDataError:
function. Callback for when character data loading fails. This function is passed whatever the failure reason is from charDataLoader.renderer:
string, default 'svg'. Set this to 'canvas' to render using a 2d canvas instead of SVG. May have better performance on some devices.Load raw character data from the Hanzi Writer CDN. Returns a promise which resolves when loading is complete.
character
The character to draw, ex '你'.
options
object containing additional configuration options. Full options available include:
charDataLoader:
function. Custom function to load charater data. See the section on Loading character data for more info on usage.onLoadCharDataSuccess:
function. Callback for when character data is loaded successfully. This function is passed the data that was loadedonLoadCharDataError:
function. Callback for when character data loading fails. This function is passed whatever the failure reason is from charDataLoader.Return an object containing scaling info which can be used when rendering raw character data in SVG.
width
number, the width of the character to be rendered in px.
height
number, height of the character to be rendered in px.
padding
number, extra padding around the character. default 0.
x:
number. The x offset used in translate.y:
number. The y offset used in translate.scale:
number. The scale used in the scale part of the transform.transform:
string. The SVG transform string which can be directly used in the transform
attribute of a <g>
element to scale and position character path strings in SVG.