[{"data":1,"prerenderedAt":918},["ShallowReactive",2],{"$f3nubjxrwpl98s":3},{"title":4,"date":5,"tags":6,"categories":10,"_id":12,"slug":13,"path":14,"document":15,"excerpt":916,"readingTimeMinutes":917},"Render three-dimensional models in `NuxtContent` with p5.js","2024-12-31T00:00:00.000Z",[7,8,9],"nuxt","p5js","3d",[11],"examples","content:blog:nuxt-p5js-3d-models","nuxt-p5js-3d-models","\u002Fblog\u002Fnuxt-p5js-3d-models",{"frontmatter":16,"meta":17,"nodes":18},{},{},[19,38,47,51,63,175,182,185,196,205,221,227,913],[20,21,22,23,27,28,31,32,37],"p",{},"Three-dimensional models, whether they be of the format ",[24,25,26],"code",{},".obj"," or ",[24,29,30],{},".stl",", can be easily rendered in your Nuxt project by using the ",[33,34,36],"a",{"href":35},"https:\u002F\u002Fp5js.org\u002F","p5js.org"," library.",[39,40,41,42,46],"blockquote",{},"Update 2025: the interactive demos on this site now link directly to the standalone ",[33,43,45],{"href":44},"https:\u002F\u002Fcmpadden.github.io\u002Fp5\u002F","p5 experiments",". The component API described below still works when embedding the GitHub Pages build of that project.",[48,49,50],null,{},"more",[20,52,53,54,57,58,62],{},"I've been using p5 for a while now to tinker and explore generative art, some of which can be found in the ",[33,55,56],{"href":56},"\u002Fexperiments"," section of this website. To use it with Nuxt, a ",[33,59,61],{"href":60},"https:\u002F\u002Fgithub.com\u002Fcmpadden\u002Fcmpadden.github.io\u002Fblob\u002F70ba674acdbe80c4a41b510a9b54edcddb19f489\u002Fplugins\u002Fp5.client.js","client-side plugin"," was created like so:",[64,65,68],"pre",{"language":66,"class":67},"js","shiki shiki-themes tokyo-night dark:tokyo-night",[24,69,71,80,81,80,105,80,107,80,130,80,138,80,149,80,160,80,165,80,170],{"class":70},"language-js",[72,73,76],"span",{"class":74,"style":75},"line","display: inline",[72,77,79],{"style":78},"color:#51597D;--shiki-light-font-style:italic","\u002F\u002F plugins\u002Fp5.client.js","\n",[72,82,83,87,91,94,98,102],{"class":74,"style":75},[72,84,86],{"style":85},"color:#7DCFFF","import",[72,88,90],{"style":89},"color:#0DB9D7"," p5",[72,92,93],{"style":85}," from",[72,95,97],{"style":96},"color:#89DDFF"," '",[72,99,101],{"style":100},"color:#9ECE6A","p5",[72,103,104],{"style":96},"'",[72,106],{"class":74,"style":75},[72,108,109,112,115,119,123,127],{"class":74,"style":75},[72,110,111],{"style":85},"export",[72,113,114],{"style":85}," default",[72,116,118],{"style":117},"color:#7AA2F7"," defineNuxtPlugin",[72,120,122],{"style":121},"color:#9ABDF5","(()",[72,124,126],{"style":125},"color:#BB9AF7"," =>",[72,128,129],{"style":121}," {",[72,131,132,136],{"class":74,"style":75},[72,133,135],{"style":134},"color:#BB9AF7;--shiki-light-font-style:italic","  return",[72,137,129],{"style":121},[72,139,140,144,147],{"class":74,"style":75},[72,141,143],{"style":142},"color:#73DACA","    provide",[72,145,146],{"style":96},":",[72,148,129],{"style":121},[72,150,151,155,158],{"class":74,"style":75},[72,152,154],{"style":153},"color:#C0CAF5","      p5",[72,156,157],{"style":96},",",[72,159,90],{"style":153},[72,161,162],{"class":74,"style":75},[72,163,164],{"style":121},"    }",[72,166,167],{"class":74,"style":75},[72,168,169],{"style":121},"  }",[72,171,172],{"class":74,"style":75},[72,173,174],{"style":121},"})",[20,176,177,178,181],{},"As I've been exploring 3d-printing lately, I wanted a way to showcase some of the models I've created directly on this website. So, the ",[24,179,180],{},"ModelPreview"," component was created, and the snippet below shows how it's embedded in markdown.",[48,183,184],{}," Low poly eevee was used as an example found here: https:\u002F\u002Fwww.thingiverse.com\u002Fthing:2931434 ",[20,186,187,188,191,192,195],{},"The Vue component was embedded in our markdown using the following syntax is used. The ",[24,189,190],{},"path"," prop with the location of the file we want to render; in this case, that file is served on the website as well in the ",[24,193,194],{},"public\u002Fmodels"," folder.",[64,197,198],{"class":67},[24,199,200],{},[72,201,202],{"class":74,"style":75},[72,203,204],{},":ModelPreview{path=\"\u002Fmodels\u002Feevee.stl\"}",[20,206,207,208,211,212,215,216,220],{},"The component was registered globally by using the ",[24,209,210],{},"ModelPreview.global.vue"," filename so that it was accessible in our markdown. Alternatively, this could have been accomplished by placing the component in the ",[24,213,214],{},"components\u002Fcontent"," folder. However, I wanted to use this component in both markdown and Vue files. See the ",[33,217,219],{"href":218},"https:\u002F\u002Fcontent.nuxt.com\u002Fusage\u002Fmarkdown#vue-components","NuxtContent"," documentation for more details.",[20,222,223,224,226],{},"The full source code for the ",[24,225,180],{}," component at the time of this writing can be found below. Not too bad!",[64,228,229],{"language":66,"class":67},[24,230,231,80,244,80,281,80,290,80,292,80,316,80,334,80,336,80,387,80,389,80,396,80,419,80,442,80,473,80,475,80,493,80,511,80,513,80,523,80,532,80,546,80,548,80,568,80,595,80,602,80,604,80,621,80,653,80,659,80,661,80,678,80,693,80,699,80,701,80,718,80,735,80,749,80,751,80,764,80,786,80,791,80,809,80,826,80,839,80,841,80,858,80,864,80,870,80,872,80,897,80,905],{"class":70},[72,232,233,237,241],{"class":74,"style":75},[72,234,236],{"style":235},"color:#BA3C97","\u003C",[72,238,240],{"style":239},"color:#F7768E","template",[72,242,243],{"style":235},">",[72,245,246,249,252,255,258,261,264,266,269,271,273,276,278],{"class":74,"style":75},[72,247,248],{"style":235},"    \u003C",[72,250,251],{"style":239},"div",[72,253,254],{"style":125}," id",[72,256,257],{"style":96},"=",[72,259,260],{"style":96},"\"",[72,262,263],{"style":100},"canvas",[72,265,260],{"style":96},[72,267,268],{"style":125}," class",[72,270,257],{"style":96},[72,272,260],{"style":96},[72,274,275],{"style":100},"h-64",[72,277,260],{"style":96},[72,279,280],{"style":235}," \u002F>",[72,282,283,286,288],{"class":74,"style":75},[72,284,285],{"style":235},"\u003C\u002F",[72,287,240],{"style":239},[72,289,243],{"style":235},[72,291],{"class":74,"style":75},[72,293,294,296,299,302,305,307,309,312,314],{"class":74,"style":75},[72,295,236],{"style":235},[72,297,298],{"style":239},"script",[72,300,301],{"style":125}," setup",[72,303,304],{"style":125}," lang",[72,306,257],{"style":96},[72,308,260],{"style":96},[72,310,311],{"style":100},"ts",[72,313,260],{"style":96},[72,315,243],{"style":235},[72,317,318,322,325,328,331],{"class":74,"style":75},[72,319,321],{"style":320},"color:#9AA5CE","const ",[72,323,324],{"style":85},"{",[72,326,327],{"style":153}," $p5",[72,329,330],{"style":85}," }",[72,332,333],{"style":320}," = useNuxtApp();",[72,335],{"class":74,"style":75},[72,337,338,340,342,345,347,350,353,357,359,362,364,366,369,372,374,376,379,382,384],{"class":74,"style":75},[72,339,321],{"style":320},[72,341,324],{"style":85},[72,343,344],{"style":153}," path",[72,346,157],{"style":96},[72,348,349],{"style":153}," backgroundColor",[72,351,352],{"style":96}," =",[72,354,356],{"style":355},"color:#FF9E64"," 100",[72,358,330],{"style":85},[72,360,361],{"style":320}," = defineProps \u003C ",[72,363,324],{"style":85},[72,365,344],{"style":153},[72,367,368],{"style":320},": ",[72,370,371],{"style":153},"string",[72,373,157],{"style":96},[72,375,349],{"style":153},[72,377,378],{"style":125},"?:",[72,380,381],{"style":153}," Number",[72,383,330],{"style":85},[72,385,386],{"style":320}," > ()",[72,388],{"class":74,"style":75},[72,390,391,394],{"class":74,"style":75},[72,392,393],{"style":320},"onMounted(() => ",[72,395,324],{"style":85},[72,397,398,401,404,407,410,413,416],{"class":74,"style":75},[72,399,400],{"style":153},"console",[72,402,403],{"style":96},".",[72,405,406],{"style":117},"log",[72,408,409],{"style":121},"(",[72,411,412],{"style":153},"backgroundColor",[72,414,415],{"style":121},")",[72,417,418],{"style":320},";",[72,420,421,424,427,429,432,436,438,440],{"class":74,"style":75},[72,422,423],{"style":153},"    const",[72,425,426],{"style":117}," sketch",[72,428,352],{"style":96},[72,430,431],{"style":121}," (",[72,433,435],{"style":434},"color:#E0AF68","s",[72,437,415],{"style":121},[72,439,126],{"style":125},[72,441,129],{"style":121},[72,443,444,448,451,453,456,458,461,463,465,467,469,471],{"class":74,"style":75},[72,445,447],{"style":446},"color:#9D7CD8;--shiki-light-font-style:italic","        const",[72,449,450],{"style":125}," c",[72,452,352],{"style":96},[72,454,455],{"style":153}," document",[72,457,403],{"style":96},[72,459,460],{"style":117},"getElementById",[72,462,409],{"style":121},[72,464,260],{"style":96},[72,466,263],{"style":100},[72,468,260],{"style":96},[72,470,415],{"style":121},[72,472,418],{"style":96},[72,474],{"class":74,"style":75},[72,476,477,479,482,484,486,488,491],{"class":74,"style":75},[72,478,447],{"style":446},[72,480,481],{"style":125}," WIDTH",[72,483,352],{"style":96},[72,485,450],{"style":153},[72,487,403],{"style":96},[72,489,490],{"style":85},"clientWidth",[72,492,418],{"style":96},[72,494,495,497,500,502,504,506,509],{"class":74,"style":75},[72,496,447],{"style":446},[72,498,499],{"style":125}," HEIGHT",[72,501,352],{"style":96},[72,503,450],{"style":153},[72,505,403],{"style":96},[72,507,508],{"style":85},"clientHeight",[72,510,418],{"style":96},[72,512],{"class":74,"style":75},[72,514,515,518,521],{"class":74,"style":75},[72,516,517],{"style":446},"        let",[72,519,520],{"style":125}," model",[72,522,418],{"style":96},[72,524,525,527,530],{"class":74,"style":75},[72,526,517],{"style":446},[72,528,529],{"style":125}," angle",[72,531,418],{"style":96},[72,533,534,536,539,541,544],{"class":74,"style":75},[72,535,517],{"style":446},[72,537,538],{"style":125}," rotate",[72,540,352],{"style":96},[72,542,543],{"style":355}," true",[72,545,418],{"style":96},[72,547],{"class":74,"style":75},[72,549,550,553,555,558,560,563,566],{"class":74,"style":75},[72,551,552],{"style":153},"        s",[72,554,403],{"style":96},[72,556,557],{"style":117},"preload",[72,559,352],{"style":96},[72,561,562],{"style":121}," () ",[72,564,565],{"style":125},"=>",[72,567,129],{"style":121},[72,569,570,573,575,578,580,583,585,587,589,591,593],{"class":74,"style":75},[72,571,572],{"style":153},"            model",[72,574,352],{"style":96},[72,576,577],{"style":153}," s",[72,579,403],{"style":96},[72,581,582],{"style":117},"loadModel",[72,584,409],{"style":121},[72,586,190],{"style":153},[72,588,157],{"style":96},[72,590,543],{"style":355},[72,592,415],{"style":121},[72,594,418],{"style":96},[72,596,597,600],{"class":74,"style":75},[72,598,599],{"style":121},"        }",[72,601,418],{"style":96},[72,603],{"class":74,"style":75},[72,605,606,608,610,613,615,617,619],{"class":74,"style":75},[72,607,552],{"style":153},[72,609,403],{"style":96},[72,611,612],{"style":117},"setup",[72,614,352],{"style":96},[72,616,562],{"style":121},[72,618,565],{"style":125},[72,620,129],{"style":121},[72,622,623,626,628,631,633,636,638,640,642,644,646,649,651],{"class":74,"style":75},[72,624,625],{"style":153},"            s",[72,627,403],{"style":96},[72,629,630],{"style":117},"createCanvas",[72,632,409],{"style":121},[72,634,635],{"style":355},"WIDTH",[72,637,157],{"style":96},[72,639,499],{"style":355},[72,641,157],{"style":96},[72,643,577],{"style":153},[72,645,403],{"style":96},[72,647,648],{"style":355},"WEBGL",[72,650,415],{"style":121},[72,652,418],{"style":96},[72,654,655,657],{"class":74,"style":75},[72,656,599],{"style":121},[72,658,418],{"style":96},[72,660],{"class":74,"style":75},[72,662,663,665,667,670,672,674,676],{"class":74,"style":75},[72,664,552],{"style":153},[72,666,403],{"style":96},[72,668,669],{"style":117},"mouseClicked",[72,671,352],{"style":96},[72,673,562],{"style":121},[72,675,565],{"style":125},[72,677,129],{"style":121},[72,679,680,683,685,688,690],{"class":74,"style":75},[72,681,682],{"style":153},"            rotate",[72,684,352],{"style":96},[72,686,687],{"style":355}," false",[72,689,418],{"style":96},[72,691,692],{"style":78}," \u002F\u002F disable object rotation on click",[72,694,695,697],{"class":74,"style":75},[72,696,599],{"style":121},[72,698,418],{"style":96},[72,700],{"class":74,"style":75},[72,702,703,705,707,710,712,714,716],{"class":74,"style":75},[72,704,552],{"style":153},[72,706,403],{"style":96},[72,708,709],{"style":117},"draw",[72,711,352],{"style":96},[72,713,562],{"style":121},[72,715,565],{"style":125},[72,717,129],{"style":121},[72,719,720,722,724,727,729,731,733],{"class":74,"style":75},[72,721,625],{"style":153},[72,723,403],{"style":96},[72,725,726],{"style":117},"background",[72,728,409],{"style":121},[72,730,412],{"style":153},[72,732,415],{"style":121},[72,734,418],{"style":96},[72,736,737,739,741,744,747],{"class":74,"style":75},[72,738,625],{"style":153},[72,740,403],{"style":96},[72,742,743],{"style":117},"lights",[72,745,746],{"style":121},"()",[72,748,418],{"style":96},[72,750],{"class":74,"style":75},[72,752,753,756,758,761],{"class":74,"style":75},[72,754,755],{"style":125},"            if",[72,757,431],{"style":121},[72,759,760],{"style":153},"rotate",[72,762,763],{"style":121},") {",[72,765,766,769,771,773,775,778,781,784],{"class":74,"style":75},[72,767,768],{"style":153},"                angle",[72,770,352],{"style":96},[72,772,577],{"style":153},[72,774,403],{"style":96},[72,776,777],{"style":85},"frameCount",[72,779,780],{"style":96}," *",[72,782,783],{"style":355}," 0.005",[72,785,418],{"style":96},[72,787,788],{"class":74,"style":75},[72,789,790],{"style":121},"            }",[72,792,793,795,797,800,802,805,807],{"class":74,"style":75},[72,794,625],{"style":153},[72,796,403],{"style":96},[72,798,799],{"style":117},"rotateX",[72,801,409],{"style":121},[72,803,804],{"style":153},"angle",[72,806,415],{"style":121},[72,808,418],{"style":96},[72,810,811,813,815,818,820,822,824],{"class":74,"style":75},[72,812,625],{"style":153},[72,814,403],{"style":96},[72,816,817],{"style":117},"rotateY",[72,819,409],{"style":121},[72,821,804],{"style":153},[72,823,415],{"style":121},[72,825,418],{"style":96},[72,827,828,830,832,835,837],{"class":74,"style":75},[72,829,625],{"style":153},[72,831,403],{"style":96},[72,833,834],{"style":117},"orbitControl",[72,836,746],{"style":121},[72,838,418],{"style":96},[72,840],{"class":74,"style":75},[72,842,843,845,847,850,852,854,856],{"class":74,"style":75},[72,844,625],{"style":153},[72,846,403],{"style":96},[72,848,849],{"style":117},"model",[72,851,409],{"style":121},[72,853,849],{"style":153},[72,855,415],{"style":121},[72,857,418],{"style":96},[72,859,860,862],{"class":74,"style":75},[72,861,599],{"style":121},[72,863,418],{"style":96},[72,865,866,868],{"class":74,"style":75},[72,867,164],{"style":121},[72,869,418],{"style":320},[72,871],{"class":74,"style":75},[72,873,874,877,879,881,884,886,889,891,893,895],{"class":74,"style":75},[72,875,876],{"style":96},"    new",[72,878,327],{"style":117},[72,880,409],{"style":121},[72,882,883],{"style":153},"sketch",[72,885,157],{"style":96},[72,887,888],{"style":96}," \"",[72,890,263],{"style":100},[72,892,260],{"style":96},[72,894,415],{"style":121},[72,896,418],{"style":320},[72,898,899,902],{"class":74,"style":75},[72,900,901],{"style":85},"}",[72,903,904],{"style":320},");",[72,906,907,909,911],{"class":74,"style":75},[72,908,285],{"style":235},[72,910,298],{"style":239},[72,912,243],{"style":235},[20,914,915],{},"Looking forward to sharing more models soon!","Threedimensional models, whether they be of the format .obj or .stl, can be easily rendered in your Nuxt project by using the p5js.org library. Update 2025: the interactive demos on this site now link directly to the standalone p5 experiments. The component API described below still works when embedding the GitHub Pages build of that project.",2,1790648870519]